Key Takeaways

  • More than 3,000 charities across North America use the Beacon nonprofit CRM platform
  • An estimated 14 million unique donor records were accessible via the exposed AWS key
  • Huntress Labs enumerated 2.3 million donor records in 11 minutes during proof-of-concept testing
  • The hardcoded AWS key remained valid for 14 months based on CloudTrail log analysis

A hardcoded AWS access key embedded in client-side JavaScript may have given threat actors a direct path into the S3 buckets and DynamoDB tables underlying Beacon, the nonprofit CRM platform used by more than 3,000 charities across North America. Researchers at Huntress Labs disclosed the finding Tuesday after a 45-day coordinated disclosure window closed without a public incident report from Beacon or its cloud provider.

The key pair — an access key ID and secret — appeared in a minified bundle served from Beacon's donor portal subdomain, `donate.beaconcrm.org`, inside a third-party analytics wrapper that initialized an AWS SDK client for real-time event streaming. The bundle was cacheable, unauthenticated, and indexed by public search engines. Anyone who viewed source could extract the credentials and, with minimal enumeration, list the buckets tied to Beacon's `prod-us-east-1` account.

What the key unlocked

Huntress confirmed the key carried `s3:ListBucket`, `s3:GetObject`, `dynamodb:Scan`, and `dynamodb:Query` permissions across a resource prefix scoped to `beacon-prod-*`. That prefix covered donor PII — names, emails, physical addresses, giving histories, and in some cases bank-tokenized payment methods stored via Stripe — for an estimated 14 million unique donor records across Beacon's tenant base. No encryption-at-rest keys were exposed, but the data itself was unencrypted in S3 and DynamoDB.

Beacon's architecture separates tenants by partition key in DynamoDB and by prefix in S3. The exposed key's IAM policy did not restrict access to a single tenant. A scripted enumeration could pull every object under `beacon-prod-donor-data/` and scan every partition in `beacon-prod-donations` without triggering rate limits or GuardDuty findings, because the calls originated from a legitimate AWS principal.

Huntress CTO Mara Velez told CRM Today the team built a proof-of-concept that enumerated 2.3 million donor records in 11 minutes before they voluntarily stopped. "This wasn't a misconfigured bucket policy," Velez said. "This was a credential baked into the frontend, shipped to every donor's browser, valid for 14 months based on CloudTrail logs we reviewed."

How it shipped

The analytics wrapper was introduced in Beacon's v4.2 release, March 2024, to feed a real-time "giving heatmap" feature sold as an upsell to enterprise-tier nonprofits. The wrapper pulled the key from a build-time environment variable injected by Beacon's CI pipeline. That variable was populated from a secret stored in GitHub Actions at the organization level — accessible to any repository in the org, including public forks used for contributor onboarding.

Beacon's security team rotated the key 18 hours after Huntress's initial report, revoked the session tokens, and forced a re-login for all donor portal sessions. They did not notify tenants, donors, or state attorneys general. A Beacon spokesperson said the company "determined no evidence of misuse" after reviewing CloudTrail and S3 access logs for the 30 days prior to rotation.

That determination rests on a gap. CloudTrail logs data-plane S3 `GetObject` calls only if object-level logging is enabled on the bucket. Beacon's buckets had it disabled. DynamoDB data-plane `Query` and `Scan` calls are not logged by CloudTrail at all. The only visible trail was the initial `ListBuckets` call made by Huntress during verification.

The CRM supply-chain angle

Beacon sits in a dense supply chain. Its donor portal embeds iframes from three payment processors, two email vendors, and a wealth-screening API. Several of those vendors inherit Beacon's subdomain via CNAME delegation, meaning a compromised Beacon credential could be used to mint signed URLs for vendor endpoints that trust the subdomain's origin.

More critically, Beacon's Salesforce connector — used by 68 percent of tenants to sync donor data into Salesforce Nonprofit Cloud — authenticates via a named credential stored in AWS Secrets Manager. The exposed key had `secretsmanager:GetSecretValue` on the `beacon-prod/connectors/salesforce/*` path. Huntress did not test whether the Salesforce OAuth refresh token could be extracted, but the IAM policy allowed it.

Beacon's connector code, reviewed by CRM Today, stores the refresh token as a plaintext string in Secrets Manager. Rotation of the AWS key does not rotate the Salesforce token. If the token was pulled, the actor could maintain persistent write access to tenant Salesforce orgs — creating, updating, or exporting donor records — until the tenant manually revokes the connected app.

Regulatory exposure

Beacon's tenant base includes hospitals, universities, and 501(c)(3) organizations subject to state breach-notification laws in California, New York, Texas, and 44 other states. Several statutes define "personal information" to include donation history when linked to identity. The exposure window — March 2024 through September 2024 — spans multiple fundraising cycles, including Giving Tuesday and year-end drives.

Beacon's silence contrasts with its competitor Virtuous, which suffered a similar frontend key leak in 2022 and published a per-tenant impact report within 72 hours. Virtuous also moved all AWS SDK calls to a serverless edge function behind WAF, eliminating client-side credentials entirely. Beacon's post-incident roadmap, shared privately with two tenants and seen by CRM Today, promises the same migration by Q2 2025.

What tenants should do now

Tenants cannot rotate the Salesforce refresh token from Beacon's dashboard. They must log into Salesforce Setup, navigate to Connected Apps OAuth Usage, locate "Beacon CRM Connector," and click Revoke. That forces a new OAuth dance on the next sync — a 10-minute operation per tenant.

Tenants should also request Beacon's CloudTrail data-plane logs for their specific S3 prefix. Beacon's multi-tenant logging architecture makes this a manual support request. Without it, there is no independent verification of "no evidence of misuse."

Finally, donors whose data passed through Beacon between March and September 2024 should treat their giving history as potentially exposed. Phishing campaigns referencing specific donation amounts, dates, and causes are a realistic follow-on threat.

Beacon's board includes two former Salesforce executives and a partner from a top-10 VC firm. The company raised a $65 million Series C in June 2024, announcing "platform hardening" as a capital priority. The exposed key shipped three months before that raise. Investors were not informed during due diligence, according to a source close to the data room.

The incident is a textbook case of frontend credential leakage in a CRM platform that markets compliance as a differentiator. Beacon's SOC 2 Type II report, renewed in August 2024, lists "no secret material in client bundles" as a control objective. The auditor did not test the donor portal's production bundle.

Huntress has released a fingerprinting script tenants can run against their donor portal hostname to detect residual exposure. Beacon has not added the fingerprint to its status page.

Frequently Asked Questions

How did the AWS access key end up in client-side JavaScript?

The key was pulled from a build-time environment variable injected by Beacon's CI pipeline into a third-party analytics wrapper that initialized an AWS SDK client for real-time event streaming.

What specific donor data was exposed in the S3 buckets and DynamoDB tables?

Donor PII including names, emails, physical addresses, giving histories, and in some cases bank-tokenized payment methods stored via Stripe across an estimated 14 million unique donor records.