misp-guard is a mitmproxy addon that inspects and blocks outgoing events to external MISP instances via sync mechanisms (pull/push/feed fetch) based on a set of customizable block rules.
23
stars
94
commits
Python
primary language
Sep 1, 2026
updated

misp-guard is a mitmproxy addon designed to apply configurable filters that prevent the unintentional leakage of sensitive threat intelligence data while facilitating controlled information sharing.
misp-guard functions as a proxy specifically designed to interact with and understand the MISP synchronization protocol. It monitors communications between MISP instances, allowing for real-time inspection and enforcement of security policies. MISP Guard effectively blocks incoming or outgoing data that matches configured filtering rules, ensuring sensitive or restricted information is not unintentionally shared.
NOTE: By default this addon will block all outgoing HTTP requests that are not required during a MISP server sync. However, individual URLs or domains can be allowed if necessary.
To prevent data leakage in high-security environments such as military networks or critical infrastructure systems, misp-guard plays a crucial role by acting as a configurable enforcement layer during MISP instance synchronization. Its fine-grained filtering capabilities allow organizations to maintain strict control over what information is shared, ensuring compliance with compartmentalization policies and mitigating the risk of accidental data exposure.
Supported block rules:
compartments_rules: Compartments can be interpreted as a VLAN where one or more MISP are living, each compartment defines to which other compartments allows to sync.taxonomies_rules:
required_taxonomies: Taxonomies that have to be present in a event, otherwise it will be blocked.allowed_tags: For each of the required_taxonomies a subset of allowed tags can be specified.blocked_tags: Tags that cannot be present in any of the event entities.blocked_distribution_levels: Blocks if the event/objects/attributes matches one of the blocked distribution levels.
"0": Organisation Only"1": Community Only"2": Connected Communities"3": All Communities"4": Sharing Group"5": Inherit Eventblocked_sharing_groups_uuids: Blocks if the event/objects/attributes matches one of the blocked sharing groups uuids.blocked_attribute_types: Blocks if the event contains an attribute matching one of this types.blocked_attribute_categories: Blocks if the event contains an attribute matching one of this categories.blocked_object_types: Blocks if the event contains an object matching one of this types.Allowlist
allowlist element.
urls The entire URL is checked and only exact calls are allowed.domains In contrast, only the domain is checked and any website behind the domain can be queried. Should only be used if adding exact URLs is not possible.Feeds
feeds element, see the Feeds section below.Instance settings
allow_sync_auth_key_refresh: If set to true, [POST]/users/resetauthkey/me requests to this instance are allowed, so the sync user authentication key can be refreshed. Defaults to false, meaning these requests are blocked as any other non sync related endpoint. Note that this setting is evaluated on the destination instance, the one owning the authentication key being refreshed.See sample config here.
misp-guard has been evaluated at Evaluation Assurance Level 2 (EAL 2) under the Common Criteria framework, covering its filtering capabilities, logging mechanisms, configuration options and integration with MISP instances.
The report documents the target of evaluation, the security target, the functional specification of every supported filtering rule, the high level design, the test plan and results, and the vulnerability assessment conducted on the addon.
sequenceDiagram
participant MISP A
participant MISP Guard
participant MISP B
rect rgb(191, 223, 255)
note right of MISP A: PUSH Events
MISP B->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP A: [GET]/servers/getVersion
MISP A->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP B: [GET]/servers/getVersion
MISP B->>MISP Guard: [HEAD]/events/view/[UUID]
note right of MISP Guard: Only `minimal` search requests to /events/index are allowed
MISP Guard->>MISP A: [HEAD]/events/view/[UUID]
MISP A->>MISP Guard: [HEAD]/events/view/[UUID]
MISP Guard->>MISP B: [HEAD]/events/view/[UUID]
rect rgb(191, 223, 255)
note left of MISP Guard: 404: If the event does not exists in MISP A
MISP B->>+MISP Guard: [POST]/events/add
note right of MISP Guard: Outgoing Event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/events/add
MISP A->>MISP Guard: [POST]/events/add
MISP Guard->>MISP B: [POST]/events/add
end
rect rgb(191, 223, 255)
note left of MISP Guard: 200: If the event already exists in MISP A
MISP B->>+MISP Guard: [POST]/events/edit/[UUID]
note right of MISP Guard: Outgoing Event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/events/edit/[UUID]
MISP A->>MISP Guard: [POST]/events/edit/[UUID]
MISP Guard->>MISP B: [POST]/events/edit/[UUID]
end
end
rect rgb(191, 223, 255)
note right of MISP A: PUSH GalaxyClusters
MISP B->>+MISP Guard: [POST]/galaxies/pushCluster
note right of MISP Guard: Outgoing Galaxy Cluster is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/galaxies/pushCluster
MISP A->>MISP Guard: [POST]/galaxies/pushCluster
MISP Guard->>MISP B: [POST]/galaxies/pushCluster
end
rect rgb(191, 223, 255)
note right of MISP A: PUSH Sightings
MISP B->>+MISP Guard: [POST]/sightings/bulkSaveSightings/[UUID]
note right of MISP Guard: Outgoing Sightings are inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/sightings/bulkSaveSightings/[UUID]
MISP A->>MISP Guard: [POST]/sightings/bulkSaveSightings/[UUID]
MISP Guard->>MISP B: [POST]/sightings/bulkSaveSightings/[UUID]
end
rect rgb(191, 223, 255)
note right of MISP A: PUSH AnalystData
MISP B->>+MISP Guard: [POST]/analyst_data/filterAnalystDataForPush
MISP A->>MISP Guard: [POST]/analyst_data/filterAnalystDataForPush
MISP Guard->>MISP B: [POST]/analyst_data/filterAnalystDataForPush
MISP B->>+MISP Guard: [POST]/analyst_data/pushAnalystData
note right of MISP Guard: Outgoing Analyst Data is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/analyst_data/pushAnalystData
MISP A->>MISP Guard: [POST]/analyst_data/pushAnalystData
MISP Guard->>MISP B: [POST]/analyst_data/pushAnalystData
end
sequenceDiagram
participant MISP A
participant MISP Guard
participant MISP B
rect rgb(191, 223, 255)
note right of MISP A: PULL Events
MISP A->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP B: [GET]/servers/getVersion
MISP B->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP A: [GET]/servers/getVersion
MISP A->>+MISP Guard: [POST]/events/index
note right of MISP Guard: Only `minimal` search requests to /events/index are allowed
MISP Guard->>-MISP B: [POST]/events/index
MISP B->>MISP Guard: [POST]/events/index
MISP Guard->>MISP A: [POST]/events/index
MISP A->>MISP Guard: [GET]/events/view/[UUID]
MISP Guard->>MISP B: [GET]/events/view/[UUID]
MISP B->>+MISP Guard: [GET]/events/view/[UUID]
note right of MISP Guard: Incoming Event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/events/view/[UUID]
MISP A->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP B: [GET]/users/view/me.json
MISP B->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP A: [GET]/users/view/me.json
end
rect rgb(191, 223, 255)
note right of MISP A: PULL ShadowAttributes
MISP A->>MISP Guard: [GET]/shadow_attributes/index
MISP Guard->>MISP B: [GET]/shadow_attributes/index
MISP B->>+MISP Guard: [GET]/shadow_attributes/index
note right of MISP Guard: Incoming Shadow Attributes are inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/shadow_attributes/index
end
rect rgb(191, 223, 255)
note right of MISP A: GalaxyClusters
MISP A->>+MISP Guard: [POST]/galaxy_clusters/restSearch
note right of MISP Guard: Only `minimal` search requests to /galaxy_clusters/restSearch are allowed
MISP Guard->>-MISP B: [POST]/galaxy_clusters/restSearch
MISP B->>MISP Guard: [POST]/galaxy_clusters/restSearch
MISP Guard->>MISP A: [POST]/galaxy_clusters/restSearch
MISP A->>MISP Guard: [GET]/galaxy_clusters/view/[UUID]
MISP Guard->>MISP B: [GET]/galaxy_clusters/view/[UUID]
MISP B->>+MISP Guard: [GET]/galaxy_clusters/view/[UUID]
note right of MISP Guard: Incoming Galaxy Cluster is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/galaxy_clusters/view/[UUID]
MISP A->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP B: [GET]/users/view/me.json
MISP B->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP A: [GET]/users/view/me.json
end
rect rgb(191, 223, 255)
note right of MISP A: PULL Sightings
MISP A->>MISP Guard: [POST]/sightings/restSearch/event
MISP Guard->>MISP B: [POST]/sightings/restSearch/event
MISP B->>+MISP Guard: [POST]/sightings/restSearch/event
note right of MISP Guard: Incoming Sightings are inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/sightings/restSearch/event
end
rect rgb(191, 223, 255)
note right of MISP A: PULL AnalystData
MISP A->>MISP Guard: [POST]/analyst_data/indexMinimal
MISP Guard->>MISP B: [POST]/analyst_data/indexMinimal
MISP B->>+MISP Guard: [POST]/analyst_data/indexMinimal
MISP Guard->>-MISP A: [POST]/analyst_data/indexMinimal
MISP A->>MISP Guard: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
MISP Guard->>MISP B: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
MISP B->>+MISP Guard: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
note right of MISP Guard: Incoming Analyst Data is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
MISP A->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP B: [GET]/users/view/me.json
MISP B->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP A: [GET]/users/view/me.json
end
NOTE: The
MISP Aserver needs to have themisp-guardhostname configured as the server hostname you are going to pull from, not theMISP Bhostname.
Remote feeds are configured under the top level feeds element, each feed defines its own set of block rules, using the same rules as the instances:
"feeds": {
"feed_osint": {
"type": "misp",
"url": "https://www.circl.lu/doc/misp/feed-osint",
"allow_caching": false,
"taxonomies_rules": {
"required_taxonomies": [],
"allowed_tags": {},
"blocked_tags": [
"tlp:red"
]
},
"blocked_distribution_levels": [],
"blocked_sharing_groups_uuids": [],
"blocked_attribute_types": [],
"blocked_attribute_categories": [],
"blocked_object_types": []
}
}
type: Feed format, only misp format feeds are supported for now.url: Base url of the feed, the directory holding the manifest.json file.allow_caching: If set to true, [GET]<FEED_URL>/hashes.csv requests are allowed, so MISP can fill its feed cache used for the feed correlation lookups. Defaults to false.Only the [GET]<FEED_URL>/manifest.json, [GET]<FEED_URL>/[UUID].json and [GET]<FEED_URL>/[UUID].asc endpoints of a configured feed are allowed, plus [GET]<FEED_URL>/hashes.csv if allow_caching is enabled. Any other request to the feed host is rejected as any other non sync related request. Only the configured instances can fetch a feed.
The [UUID].asc signature of a protected event is passed through, it holds no event data and the event it signs is either passed through untouched or rejected as a whole, so the signature validation done by MISP is not affected.
NOTE: The feed cache (
hashes.csv) only holds the md5 hashes of the attribute values and the uuid of the event they belong to, there are no tags, types, categories or distribution levels to match the block rules against, so its content is passed through as is. An event that the block rules would reject can still contribute its value hashes to the cache, which is why fetching it has to be explicitly enabled per feed.
sequenceDiagram
participant MISP A
participant MISP Guard
participant Feed
rect rgb(191, 223, 255)
note right of MISP A: FETCH Feed
MISP A->>MISP Guard: [GET]/manifest.json
MISP Guard->>Feed: [GET]/manifest.json
Feed->>+MISP Guard: [GET]/manifest.json
note right of MISP Guard: The event metadata of the manifest is inspected and the events matching a block rule are removed from it
MISP Guard->>-MISP A: [GET]/manifest.json
MISP A->>MISP Guard: [GET]/[UUID].json
MISP Guard->>Feed: [GET]/[UUID].json
Feed->>+MISP Guard: [GET]/[UUID].json
note right of MISP Guard: The incoming event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/[UUID].json
rect rgb(191, 223, 255)
note left of MISP Guard: Only for protected events
MISP A->>MISP Guard: [GET]/[UUID].asc
MISP Guard->>Feed: [GET]/[UUID].asc
Feed->>MISP Guard: [GET]/[UUID].asc
MISP Guard->>MISP A: [GET]/[UUID].asc
end
end
rect rgb(191, 223, 255)
note right of MISP A: CACHE Feed
MISP A->>+MISP Guard: [GET]/hashes.csv
note right of MISP Guard: Rejected with 403 unless the feed has `allow_caching` enabled, the feed cache content can not be filtered
MISP Guard->>-Feed: [GET]/hashes.csv
Feed->>MISP Guard: [GET]/hashes.csv
MISP Guard->>MISP A: [GET]/hashes.csv
end
The rules are checked in two stages:
manifest.json document holds the metadata (tags, ...) of every event of the feed, the events matching a block rule are removed from the manifest so they are never fetched. The manifest metadata only carries the event tags, so in practice only the taxonomies_rules apply at this stage.[UUID].json event is inspected with the full set of block rules, the same way as an event pulled from another instance, and is rejected with a 403 if any rule matches.NOTE: Feed events do not carry a distribution level nor a sharing group, those rules only apply to the entities of the event that do define them.
venv (recommended).$ git clone https://github.com/MISP/misp-guard.git
$ cd src/
$ apt install python3.12-venv
$ python3.12 -m venv .venv
$ source .venv/bin/activate
$ pip3 install -r requirements.txt
Define your block rules in the config.json file.
Start mitmproxy with the mispguard addon:
$ mitmdump -s mispguard.py -p 8888 --certs *=cert.pem --set config=config.json
Loading script mispguard.py
MispGuard initialized
Proxy server listening at *:8888
Add -k to accept self-signed certificates.
Configure the proxy in your MISP instance, set the following MISP Proxy.host and Proxy.port settings accordingly.
Done, outgoing MISP sync requests will be inspected and dropped according to the specified block rules.
NOTE: add
-vtomitmdumpto increase verbosity and display debug logs.
$ pip install pytest pytest-asyncio
$ src src/
$ pytest
You can also run misp-guard using the misp-docker/misp-guard.
You need to mount a valid config.json, use the misp-docker sample config.json file as the misp-guard container relies on the a hardcoded instance named misp_container to replace the IP provided.
Example:
docker run --name misp-guard \
-e MISP_IP=172.19.0.7 \
-e GUARD_PORT=8888 \
-e GUARD_ARGS="--ssl-insecure -v" \
-p 8888:8888 \
-v /home/user/misp-guard/src/config.json:/config.json:ro \
ghcr.io/misp/misp-docker/misp-guard:latest
Environment variables:
misp-guard proxy.mitmproxy will be running, has to match Proxy.port MISP Setting.mitmproxy utility.Python
100.0%
misp-guard is a mitmproxy addon that inspects and blocks outgoing events to external MISP instances via sync mechanisms (pull/push/feed fetch) based on a set of customizable block rules.
23
stars
94
commits
Python
primary language
Sep 1, 2026
updated

misp-guard is a mitmproxy addon designed to apply configurable filters that prevent the unintentional leakage of sensitive threat intelligence data while facilitating controlled information sharing.
misp-guard functions as a proxy specifically designed to interact with and understand the MISP synchronization protocol. It monitors communications between MISP instances, allowing for real-time inspection and enforcement of security policies. MISP Guard effectively blocks incoming or outgoing data that matches configured filtering rules, ensuring sensitive or restricted information is not unintentionally shared.
NOTE: By default this addon will block all outgoing HTTP requests that are not required during a MISP server sync. However, individual URLs or domains can be allowed if necessary.
To prevent data leakage in high-security environments such as military networks or critical infrastructure systems, misp-guard plays a crucial role by acting as a configurable enforcement layer during MISP instance synchronization. Its fine-grained filtering capabilities allow organizations to maintain strict control over what information is shared, ensuring compliance with compartmentalization policies and mitigating the risk of accidental data exposure.
Supported block rules:
compartments_rules: Compartments can be interpreted as a VLAN where one or more MISP are living, each compartment defines to which other compartments allows to sync.taxonomies_rules:
required_taxonomies: Taxonomies that have to be present in a event, otherwise it will be blocked.allowed_tags: For each of the required_taxonomies a subset of allowed tags can be specified.blocked_tags: Tags that cannot be present in any of the event entities.blocked_distribution_levels: Blocks if the event/objects/attributes matches one of the blocked distribution levels.
"0": Organisation Only"1": Community Only"2": Connected Communities"3": All Communities"4": Sharing Group"5": Inherit Eventblocked_sharing_groups_uuids: Blocks if the event/objects/attributes matches one of the blocked sharing groups uuids.blocked_attribute_types: Blocks if the event contains an attribute matching one of this types.blocked_attribute_categories: Blocks if the event contains an attribute matching one of this categories.blocked_object_types: Blocks if the event contains an object matching one of this types.Allowlist
allowlist element.
urls The entire URL is checked and only exact calls are allowed.domains In contrast, only the domain is checked and any website behind the domain can be queried. Should only be used if adding exact URLs is not possible.Feeds
feeds element, see the Feeds section below.Instance settings
allow_sync_auth_key_refresh: If set to true, [POST]/users/resetauthkey/me requests to this instance are allowed, so the sync user authentication key can be refreshed. Defaults to false, meaning these requests are blocked as any other non sync related endpoint. Note that this setting is evaluated on the destination instance, the one owning the authentication key being refreshed.See sample config here.
misp-guard has been evaluated at Evaluation Assurance Level 2 (EAL 2) under the Common Criteria framework, covering its filtering capabilities, logging mechanisms, configuration options and integration with MISP instances.
The report documents the target of evaluation, the security target, the functional specification of every supported filtering rule, the high level design, the test plan and results, and the vulnerability assessment conducted on the addon.
sequenceDiagram
participant MISP A
participant MISP Guard
participant MISP B
rect rgb(191, 223, 255)
note right of MISP A: PUSH Events
MISP B->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP A: [GET]/servers/getVersion
MISP A->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP B: [GET]/servers/getVersion
MISP B->>MISP Guard: [HEAD]/events/view/[UUID]
note right of MISP Guard: Only `minimal` search requests to /events/index are allowed
MISP Guard->>MISP A: [HEAD]/events/view/[UUID]
MISP A->>MISP Guard: [HEAD]/events/view/[UUID]
MISP Guard->>MISP B: [HEAD]/events/view/[UUID]
rect rgb(191, 223, 255)
note left of MISP Guard: 404: If the event does not exists in MISP A
MISP B->>+MISP Guard: [POST]/events/add
note right of MISP Guard: Outgoing Event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/events/add
MISP A->>MISP Guard: [POST]/events/add
MISP Guard->>MISP B: [POST]/events/add
end
rect rgb(191, 223, 255)
note left of MISP Guard: 200: If the event already exists in MISP A
MISP B->>+MISP Guard: [POST]/events/edit/[UUID]
note right of MISP Guard: Outgoing Event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/events/edit/[UUID]
MISP A->>MISP Guard: [POST]/events/edit/[UUID]
MISP Guard->>MISP B: [POST]/events/edit/[UUID]
end
end
rect rgb(191, 223, 255)
note right of MISP A: PUSH GalaxyClusters
MISP B->>+MISP Guard: [POST]/galaxies/pushCluster
note right of MISP Guard: Outgoing Galaxy Cluster is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/galaxies/pushCluster
MISP A->>MISP Guard: [POST]/galaxies/pushCluster
MISP Guard->>MISP B: [POST]/galaxies/pushCluster
end
rect rgb(191, 223, 255)
note right of MISP A: PUSH Sightings
MISP B->>+MISP Guard: [POST]/sightings/bulkSaveSightings/[UUID]
note right of MISP Guard: Outgoing Sightings are inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/sightings/bulkSaveSightings/[UUID]
MISP A->>MISP Guard: [POST]/sightings/bulkSaveSightings/[UUID]
MISP Guard->>MISP B: [POST]/sightings/bulkSaveSightings/[UUID]
end
rect rgb(191, 223, 255)
note right of MISP A: PUSH AnalystData
MISP B->>+MISP Guard: [POST]/analyst_data/filterAnalystDataForPush
MISP A->>MISP Guard: [POST]/analyst_data/filterAnalystDataForPush
MISP Guard->>MISP B: [POST]/analyst_data/filterAnalystDataForPush
MISP B->>+MISP Guard: [POST]/analyst_data/pushAnalystData
note right of MISP Guard: Outgoing Analyst Data is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/analyst_data/pushAnalystData
MISP A->>MISP Guard: [POST]/analyst_data/pushAnalystData
MISP Guard->>MISP B: [POST]/analyst_data/pushAnalystData
end
sequenceDiagram
participant MISP A
participant MISP Guard
participant MISP B
rect rgb(191, 223, 255)
note right of MISP A: PULL Events
MISP A->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP B: [GET]/servers/getVersion
MISP B->>MISP Guard: [GET]/servers/getVersion
MISP Guard->>MISP A: [GET]/servers/getVersion
MISP A->>+MISP Guard: [POST]/events/index
note right of MISP Guard: Only `minimal` search requests to /events/index are allowed
MISP Guard->>-MISP B: [POST]/events/index
MISP B->>MISP Guard: [POST]/events/index
MISP Guard->>MISP A: [POST]/events/index
MISP A->>MISP Guard: [GET]/events/view/[UUID]
MISP Guard->>MISP B: [GET]/events/view/[UUID]
MISP B->>+MISP Guard: [GET]/events/view/[UUID]
note right of MISP Guard: Incoming Event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/events/view/[UUID]
MISP A->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP B: [GET]/users/view/me.json
MISP B->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP A: [GET]/users/view/me.json
end
rect rgb(191, 223, 255)
note right of MISP A: PULL ShadowAttributes
MISP A->>MISP Guard: [GET]/shadow_attributes/index
MISP Guard->>MISP B: [GET]/shadow_attributes/index
MISP B->>+MISP Guard: [GET]/shadow_attributes/index
note right of MISP Guard: Incoming Shadow Attributes are inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/shadow_attributes/index
end
rect rgb(191, 223, 255)
note right of MISP A: GalaxyClusters
MISP A->>+MISP Guard: [POST]/galaxy_clusters/restSearch
note right of MISP Guard: Only `minimal` search requests to /galaxy_clusters/restSearch are allowed
MISP Guard->>-MISP B: [POST]/galaxy_clusters/restSearch
MISP B->>MISP Guard: [POST]/galaxy_clusters/restSearch
MISP Guard->>MISP A: [POST]/galaxy_clusters/restSearch
MISP A->>MISP Guard: [GET]/galaxy_clusters/view/[UUID]
MISP Guard->>MISP B: [GET]/galaxy_clusters/view/[UUID]
MISP B->>+MISP Guard: [GET]/galaxy_clusters/view/[UUID]
note right of MISP Guard: Incoming Galaxy Cluster is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/galaxy_clusters/view/[UUID]
MISP A->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP B: [GET]/users/view/me.json
MISP B->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP A: [GET]/users/view/me.json
end
rect rgb(191, 223, 255)
note right of MISP A: PULL Sightings
MISP A->>MISP Guard: [POST]/sightings/restSearch/event
MISP Guard->>MISP B: [POST]/sightings/restSearch/event
MISP B->>+MISP Guard: [POST]/sightings/restSearch/event
note right of MISP Guard: Incoming Sightings are inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [POST]/sightings/restSearch/event
end
rect rgb(191, 223, 255)
note right of MISP A: PULL AnalystData
MISP A->>MISP Guard: [POST]/analyst_data/indexMinimal
MISP Guard->>MISP B: [POST]/analyst_data/indexMinimal
MISP B->>+MISP Guard: [POST]/analyst_data/indexMinimal
MISP Guard->>-MISP A: [POST]/analyst_data/indexMinimal
MISP A->>MISP Guard: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
MISP Guard->>MISP B: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
MISP B->>+MISP Guard: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
note right of MISP Guard: Incoming Analyst Data is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json
MISP A->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP B: [GET]/users/view/me.json
MISP B->>MISP Guard: [GET]/users/view/me.json
MISP Guard->>MISP A: [GET]/users/view/me.json
end
NOTE: The
MISP Aserver needs to have themisp-guardhostname configured as the server hostname you are going to pull from, not theMISP Bhostname.
Remote feeds are configured under the top level feeds element, each feed defines its own set of block rules, using the same rules as the instances:
"feeds": {
"feed_osint": {
"type": "misp",
"url": "https://www.circl.lu/doc/misp/feed-osint",
"allow_caching": false,
"taxonomies_rules": {
"required_taxonomies": [],
"allowed_tags": {},
"blocked_tags": [
"tlp:red"
]
},
"blocked_distribution_levels": [],
"blocked_sharing_groups_uuids": [],
"blocked_attribute_types": [],
"blocked_attribute_categories": [],
"blocked_object_types": []
}
}
type: Feed format, only misp format feeds are supported for now.url: Base url of the feed, the directory holding the manifest.json file.allow_caching: If set to true, [GET]<FEED_URL>/hashes.csv requests are allowed, so MISP can fill its feed cache used for the feed correlation lookups. Defaults to false.Only the [GET]<FEED_URL>/manifest.json, [GET]<FEED_URL>/[UUID].json and [GET]<FEED_URL>/[UUID].asc endpoints of a configured feed are allowed, plus [GET]<FEED_URL>/hashes.csv if allow_caching is enabled. Any other request to the feed host is rejected as any other non sync related request. Only the configured instances can fetch a feed.
The [UUID].asc signature of a protected event is passed through, it holds no event data and the event it signs is either passed through untouched or rejected as a whole, so the signature validation done by MISP is not affected.
NOTE: The feed cache (
hashes.csv) only holds the md5 hashes of the attribute values and the uuid of the event they belong to, there are no tags, types, categories or distribution levels to match the block rules against, so its content is passed through as is. An event that the block rules would reject can still contribute its value hashes to the cache, which is why fetching it has to be explicitly enabled per feed.
sequenceDiagram
participant MISP A
participant MISP Guard
participant Feed
rect rgb(191, 223, 255)
note right of MISP A: FETCH Feed
MISP A->>MISP Guard: [GET]/manifest.json
MISP Guard->>Feed: [GET]/manifest.json
Feed->>+MISP Guard: [GET]/manifest.json
note right of MISP Guard: The event metadata of the manifest is inspected and the events matching a block rule are removed from it
MISP Guard->>-MISP A: [GET]/manifest.json
MISP A->>MISP Guard: [GET]/[UUID].json
MISP Guard->>Feed: [GET]/[UUID].json
Feed->>+MISP Guard: [GET]/[UUID].json
note right of MISP Guard: The incoming event is inspected and rejected with 403 if any block rule matches
MISP Guard->>-MISP A: [GET]/[UUID].json
rect rgb(191, 223, 255)
note left of MISP Guard: Only for protected events
MISP A->>MISP Guard: [GET]/[UUID].asc
MISP Guard->>Feed: [GET]/[UUID].asc
Feed->>MISP Guard: [GET]/[UUID].asc
MISP Guard->>MISP A: [GET]/[UUID].asc
end
end
rect rgb(191, 223, 255)
note right of MISP A: CACHE Feed
MISP A->>+MISP Guard: [GET]/hashes.csv
note right of MISP Guard: Rejected with 403 unless the feed has `allow_caching` enabled, the feed cache content can not be filtered
MISP Guard->>-Feed: [GET]/hashes.csv
Feed->>MISP Guard: [GET]/hashes.csv
MISP Guard->>MISP A: [GET]/hashes.csv
end
The rules are checked in two stages:
manifest.json document holds the metadata (tags, ...) of every event of the feed, the events matching a block rule are removed from the manifest so they are never fetched. The manifest metadata only carries the event tags, so in practice only the taxonomies_rules apply at this stage.[UUID].json event is inspected with the full set of block rules, the same way as an event pulled from another instance, and is rejected with a 403 if any rule matches.NOTE: Feed events do not carry a distribution level nor a sharing group, those rules only apply to the entities of the event that do define them.
venv (recommended).$ git clone https://github.com/MISP/misp-guard.git
$ cd src/
$ apt install python3.12-venv
$ python3.12 -m venv .venv
$ source .venv/bin/activate
$ pip3 install -r requirements.txt
Define your block rules in the config.json file.
Start mitmproxy with the mispguard addon:
$ mitmdump -s mispguard.py -p 8888 --certs *=cert.pem --set config=config.json
Loading script mispguard.py
MispGuard initialized
Proxy server listening at *:8888
Add -k to accept self-signed certificates.
Configure the proxy in your MISP instance, set the following MISP Proxy.host and Proxy.port settings accordingly.
Done, outgoing MISP sync requests will be inspected and dropped according to the specified block rules.
NOTE: add
-vtomitmdumpto increase verbosity and display debug logs.
$ pip install pytest pytest-asyncio
$ src src/
$ pytest
You can also run misp-guard using the misp-docker/misp-guard.
You need to mount a valid config.json, use the misp-docker sample config.json file as the misp-guard container relies on the a hardcoded instance named misp_container to replace the IP provided.
Example:
docker run --name misp-guard \
-e MISP_IP=172.19.0.7 \
-e GUARD_PORT=8888 \
-e GUARD_ARGS="--ssl-insecure -v" \
-p 8888:8888 \
-v /home/user/misp-guard/src/config.json:/config.json:ro \
ghcr.io/misp/misp-docker/misp-guard:latest
Environment variables:
misp-guard proxy.mitmproxy will be running, has to match Proxy.port MISP Setting.mitmproxy utility.Python
100.0%