Skip to main content

Salesforce Heroku Connect detection

Vulkro's Heroku Connect detector pack (src/security/sf_heroku_connect.rs) covers the bridge between a Salesforce org and a Heroku Postgres database. Heroku Connect replicates SObjects bidirectionally based on a JSON mapping configuration; the questions this detector pack answers are whether sensitive fields land on the Heroku side encrypted, whether write-back resolves conflicts, and whether the connection URL or REST API token is committed in plaintext.

The detector activates when the project root contains any of three canonical markers:

  • a mapping.json (any path) carrying both connection_name and object_name keys (the Heroku Connect mapping shape)
  • a Procfile declaring a heroku-connect: worker
  • an app.json (or app.yml / app.yaml) referencing the herokuconnect add-on

A project with none of the three markers returns zero findings without entering the per-rule code paths.

Rules

IDSeverityWhat it catches
HC-001HighHeroku Connect mapping replicates a sensitive Salesforce field (SSN__c, DateOfBirth, Patient_MRN__c, bank_account__c, medical_record_number__c, and similar) into Heroku Postgres without a transform rule or mapped_field_name masking. The default Heroku Connect sync is a verbatim column copy, so the regulated value lands in the salesforce schema in cleartext. HIPAA, PCI, and GDPR controls that apply on the Salesforce side do not extend to the Postgres copy unless configured explicitly.
HC-002HighA SQL migration or schema.sql references a Heroku Connect mapped column against the salesforce schema, but no pgcrypto extension, pgp_sym_encrypt(...), or crypt(...) call sits anywhere in the project's SQL. The sensitive Salesforce value persists on Heroku in cleartext; a Postgres backup or pg_dump artefact carries the raw regulated data.
HC-003MediumMapping enables Salesforce write-back ("write_to_salesforce": true) but does not declare a "resolve_conflicts" strategy ("newer_record_wins", "salesforce_wins", "postgres_wins", etc). A concurrent edit on the Salesforce side and the Heroku side produces an orphan or silently overwritten record.
HC-004HighA literal postgres://user:password@host:port/db connection URL committed in app.json, app.yml, config-vars.json, or a Heroku Connect configuration file. Heroku app configs in the repo are readable by anyone with checkout access; a plaintext password is a same-day rotation incident.
HC-005MediumA literal Heroku Connect REST API token (connection_string, bearer, or X-HC-API-Token value) committed in source. The REST API authenticates via a bearer token that carries full control over the mapping configuration; a leaked token lets an attacker reshape the bidirectional sync, add their own mapping, or exfiltrate Salesforce data to a Postgres they control.

Pro gate

Pro-only. Gated by license::Feature::HerokuConnect. The vulkro scan invocation detects Heroku Connect markers in the project and prompts for a Pro license before running the HC-* rules. Heroku Connect projects are often standalone Node, Java, or Ruby apps with no Apex sources on the same machine, so the gate is wired at the scan entry independently of the language list. Native scanners for the project's other languages still run.

Example finding

Severity: High
Rule: HC-001
File: heroku-connect/mapping.json
Line: 42
Message: HC-001: Heroku Connect mapping in
`heroku-connect/mapping.json` replicates the sensitive
Salesforce field `SSN__c` into Heroku Postgres without
a `transform` rule or `mapped_field_name` masking. The
default Heroku Connect sync is a verbatim column copy,
so the regulated value lands in the `salesforce`
schema in cleartext (CWE-311). HIPAA, PCI, or GDPR
controls that apply on the Salesforce side do not
extend to the Heroku Postgres copy unless you
configure them explicitly.

See also