Context
received through the security mail
be.pdf.gov.tools (Intersect Budget Discussion / Proposal Platform) — Strapi Public Role Has
find/findOne Enabled on 21 of 31 Collections; 2,832 Individual Votes, Real Email Addresses, and
Company Affiliations Exposed; GDPR Art. 33 / 34 Notifiable
Steps to reproduce
Critical Privacy Impacts
- Voter De-Anonymisation at Web3 Scale
The bd-poll-votes collection ships 2,832 individual vote rows, each containing the voter's drep_id (28-byte
blake2b-224 hash = on-chain Cardano DRep credential), the specific poll, the YES/NO vote choice, and the
delegated ADA voting power. The first page alone exposes 23 distinct DRep IDs with ~3 billion ADA YES voting
power and ~8.9 billion ADA NO voting power. Extrapolated to all 2,832 rows, this is the entire off-chain advisory vote
history of the platform, fully linked to on-chain DRep identities:
$ curl -sS "https://be.pdf.gov.tools/api/bd-poll-votes?pagination%5BpageSize%5D=3"
| jq '.meta, .data[].attributes'
{
"pagination": {"page":1,"pageSize":3,"pageCount":944,"total":2832}
}
{
"user_id": "1274",
"bd_poll_id": "50",
"vote_result": true,
"drep_id": "957ff6477708440672253092e9682ad0c90c512d8cc0218729f922c3",
"drep_voting_power":"210201714730",
"createdAt": "2025-04-04T21:28:31.361Z"
}
- Direct PII Exposure — Real Email Addresses
The bd-proposal-ownerships collection contains a social_handles free-text field that routinely contains real email
addresses. Confirmed examples include an Intersect employee email (lorenzo.bruno+44@intersectmbo.org),
external contributor emails, and company/group affiliations (Cardano Foundation, Anastasia Labs, Aira Co. Ltd.,
Cryptofluency LLC, DripDropz LLC, ELK gmbh, Bondex Ecosystem Ltd, etc.):
$ curl -sS "https://be.pdf.gov.tools/api/bd-proposal-ownerships?pagination%5BpageSize%5D=100" \
| jq -r '.data[].attributes | [.social_handles, .company_name, .submited_on_behalf] | @tsv' \
| grep -E '@[A-Za-z0-9.-]+\.' | head
lorenzo.bruno+44@intersectmbo.org Individual
engie@matou.nz Individual
lorenzo@email.com Individual
... (more)
- Cross-Collection Re-Identification Join Graph
The platform was never designed to publish the join between its tables, but the unauthenticated access makes the full
graph available:
- Vote-Buying / Coercion Attack Surface
Once a vote-to-voter mapping is public, attackers can construct verifiable vote-buying markets ('pay me X ADA and I
will vote YES on poll P — verifiable here') because anyone can independently confirm the published bd-poll-votes
after the vote. This is the canonical Web3 governance attack the Cardano CIP-1694 designers explicitly designed to
prevent.
Confirmed Collection Counts
collection HTTP total
auth-challenges 200 1,733
bd-poll-votes 200 2,832
bds 200 715
bd-proposal-details 200 835
bd-proposal-ownerships 200 768
proposals 200 (147 KB first page)
# Write paths correctly locked:
$ curl -sS -X POST "https://be.pdf.gov.tools/api/bd-poll-votes" \
-H "Content-Type: application/json" -d "{}"
{"data":null,"error":{"status":403,"name":"ForbiddenError","message":"Forbidden"}}
Actual behavior
Impact
• GDPR Art. 33 / 34 notification required. Real, identifiable email addresses of individuals are publicly
accessible without authentication. The 72-hour supervisory-authority notification window begins on awareness.
Individual notification to affected data subjects is also likely required.
• Retroactive Web3 governance vote de-anonymisation. 2,832 rows mapping DRep on-chain identities to
specific YES/NO votes on specific polls cannot be undone. Even after the collections are locked, any party who
scraped the data before the fix holds a permanent vote-to-voter map for the platform's entire advisory-poll
history.
• Vote-buying and coercion. The voter+vote linkage enables verifiable vote-buying markets and coercion
attacks against DReps whose votes are now a matter of public record, contrary to the privacy model off-chain
advisory polls were designed to provide.
• Cross-collection re-identification. Joining the publicly accessible tables produces a complete
de-anonymisation chain: email address « wallet credential « DRep identity « vote history « proposal
authorship.
• Pseudo-anonymous draft leak. bds and bd-proposal-details expose drafts that were never intended for
public release, including test/sandbox content and unfinished proposal narratives. Authors who used the platform
as a draft tool see their unfinished work published.
• Systemic misconfiguration pattern. The same Strapi instance (be.pdf.gov.tools) shares UUID
e4220d9f-5b33-4174-bca2-17dd38e96044 with api.members.intersectmbo.org, confirmed via /admin/init. The
misconfiguration is likely cloned to the sister instance and should be audited there as well.
Expected behavior
Remediation
• Immediate (P0): In Strapi admin ® Settings ® Roles ® Public: revoke find and findOne on every
collection containing PII or governance-vote data. At minimum immediately revoke: auth-challenges,
bd-poll-votes, bd-proposal-details, bd-proposal-ownerships, bds, proposal-contents,
polls, bd-polls, proposals. Move them behind the Authenticated role.
• Immediate (P0 — GDPR): Treat this as a personal data breach under GDPR. File a supervisory-authority
notification within 72 hours of awareness. Assess whether affected individuals (email-address holders,
contributing organisations) must also be notified individually under Art. 34.
• Short-Term: Review field-level Strapi permissions. Even after collections are restricted to authenticated users,
sensitive fields (drep_id, drep_voting_power, social_handles, user_id, user_govtool_username)
should only be returned via dedicated controller methods that aggregate or anonymise appropriately.
• Short-Term: Audit the sister Strapi instance at api.members.intersectmbo.org (shares the same admin
UUID). Apply the same role-permission audit there.
• Short-Term: Treat the 2,832 existing vote rows as permanently compromised in privacy terms. Re-running
future polls with a fixed configuration does not undo past leaks. Publish a public disclosure statement so DReps
can recalibrate their prior privacy expectation.
• Long-Term: Add an automated test to CI: on every deploy, send an unauthenticated GET to every Strapi
collection and fail the build if any non-allowlisted collection returns HTTP 200 with data.
Context
received through the security mail
be.pdf.gov.tools (Intersect Budget Discussion / Proposal Platform) — Strapi Public Role Has
find/findOne Enabled on 21 of 31 Collections; 2,832 Individual Votes, Real Email Addresses, and
Company Affiliations Exposed; GDPR Art. 33 / 34 Notifiable
Steps to reproduce
Critical Privacy Impacts
The bd-poll-votes collection ships 2,832 individual vote rows, each containing the voter's drep_id (28-byte
blake2b-224 hash = on-chain Cardano DRep credential), the specific poll, the YES/NO vote choice, and the
delegated ADA voting power. The first page alone exposes 23 distinct DRep IDs with ~3 billion ADA YES voting
power and ~8.9 billion ADA NO voting power. Extrapolated to all 2,832 rows, this is the entire off-chain advisory vote
history of the platform, fully linked to on-chain DRep identities:
The bd-proposal-ownerships collection contains a social_handles free-text field that routinely contains real email
addresses. Confirmed examples include an Intersect employee email (lorenzo.bruno+44@intersectmbo.org),
external contributor emails, and company/group affiliations (Cardano Foundation, Anastasia Labs, Aira Co. Ltd.,
Cryptofluency LLC, DripDropz LLC, ELK gmbh, Bondex Ecosystem Ltd, etc.):
The platform was never designed to publish the join between its tables, but the unauthenticated access makes the full
graph available:
Once a vote-to-voter mapping is public, attackers can construct verifiable vote-buying markets ('pay me X ADA and I
will vote YES on poll P — verifiable here') because anyone can independently confirm the published bd-poll-votes
after the vote. This is the canonical Web3 governance attack the Cardano CIP-1694 designers explicitly designed to
prevent.
Confirmed Collection Counts
Actual behavior
Impact
• GDPR Art. 33 / 34 notification required. Real, identifiable email addresses of individuals are publicly
accessible without authentication. The 72-hour supervisory-authority notification window begins on awareness.
Individual notification to affected data subjects is also likely required.
• Retroactive Web3 governance vote de-anonymisation. 2,832 rows mapping DRep on-chain identities to
specific YES/NO votes on specific polls cannot be undone. Even after the collections are locked, any party who
scraped the data before the fix holds a permanent vote-to-voter map for the platform's entire advisory-poll
history.
• Vote-buying and coercion. The voter+vote linkage enables verifiable vote-buying markets and coercion
attacks against DReps whose votes are now a matter of public record, contrary to the privacy model off-chain
advisory polls were designed to provide.
• Cross-collection re-identification. Joining the publicly accessible tables produces a complete
de-anonymisation chain: email address « wallet credential « DRep identity « vote history « proposal
authorship.
• Pseudo-anonymous draft leak. bds and bd-proposal-details expose drafts that were never intended for
public release, including test/sandbox content and unfinished proposal narratives. Authors who used the platform
as a draft tool see their unfinished work published.
• Systemic misconfiguration pattern. The same Strapi instance (be.pdf.gov.tools) shares UUID
e4220d9f-5b33-4174-bca2-17dd38e96044 with api.members.intersectmbo.org, confirmed via /admin/init. The
misconfiguration is likely cloned to the sister instance and should be audited there as well.
Expected behavior
Remediation
• Immediate (P0): In Strapi admin ® Settings ® Roles ® Public: revoke find and findOne on every
collection containing PII or governance-vote data. At minimum immediately revoke: auth-challenges,
bd-poll-votes, bd-proposal-details, bd-proposal-ownerships, bds, proposal-contents,
polls, bd-polls, proposals. Move them behind the Authenticated role.
• Immediate (P0 — GDPR): Treat this as a personal data breach under GDPR. File a supervisory-authority
notification within 72 hours of awareness. Assess whether affected individuals (email-address holders,
contributing organisations) must also be notified individually under Art. 34.
• Short-Term: Review field-level Strapi permissions. Even after collections are restricted to authenticated users,
sensitive fields (drep_id, drep_voting_power, social_handles, user_id, user_govtool_username)
should only be returned via dedicated controller methods that aggregate or anonymise appropriately.
• Short-Term: Audit the sister Strapi instance at api.members.intersectmbo.org (shares the same admin
UUID). Apply the same role-permission audit there.
• Short-Term: Treat the 2,832 existing vote rows as permanently compromised in privacy terms. Re-running
future polls with a fixed configuration does not undo past leaks. Publish a public disclosure statement so DReps
can recalibrate their prior privacy expectation.
• Long-Term: Add an automated test to CI: on every deploy, send an unauthenticated GET to every Strapi
collection and fail the build if any non-allowlisted collection returns HTTP 200 with data.