Skip to main content

21 posts tagged with "Salesforce"

Salesforce security research, from Apex and Flows to the live org.

View All Tags

Why Salesforce org security needs scheduled scans

· 7 min read
Vulkro
Security research

The org your last security review described no longer exists. Since then an administrator granted a permission set "for the migration" and never took it back. A connected app was approved so a vendor could run a trial. A session timeout was relaxed because an integration kept dropping. The guest profile was edited the week a new Experience Cloud page launched. Each change was reasonable on the day. None of it is in your repository, and none of it was reviewed.

That is configuration drift, and in Salesforce it is the normal state of things. The platform is designed to be changed in Setup, by people who are not developers, without a deploy.

AgentExchange Security Review false positives: what reviewers accept

· 9 min read
Vulkro
Security research

Every package that goes through the AgentExchange (formerly AppExchange) Security Review arrives with scanner output, and almost all scanner output contains false positives. A CRUD finding on a custom setting. A sharing finding on a class that declares inherited sharing. A SOQL injection finding on a query where every value is a bind. The security review false positive document is where you explain each of those, and it decides whether a reviewer spends their time on your real risks or on questions about your noise.

Salesforce treats the document as part of the submission. Its packaging guide has a page on how to document your responses to false positives, offers a template, and asks for the code location and the reason the code is not vulnerable for each flagged issue. If the explanation will not hold up, the guidance is to change the code instead.

Apex SOQL injection: examples, fixes and how to find it

· 10 min read
Vulkro
Security research

Apex SOQL injection happens when a value the caller controls is pasted into a query string and the string is run with Database.query. The caller can then change what the query means: widen a filter, drop a condition, or sort and page through records the code never meant to return. SOQL cannot delete or update data the way SQL injection can, but reading the wrong records is usually the whole breach.

It is also one of the oldest findings in Salesforce security reviews, and it keeps coming back because dynamic queries are genuinely useful. Search screens, list views with a sort column, filter builders and admin tools all assemble queries at runtime.

This post shows the common vulnerable shapes, the fix for each (static queries, bind variables, Database.queryWithBinds, and allowlisting names through Schema describe), where String.escapeSingleQuotes stops helping, and how Vulkro for Salesforce traces the flow from the caller to the query.

Experience Cloud guest user security: a hardening checklist

· 9 min read
Vulkro
Security research

Experience Cloud guest user security comes down to one fact: whatever the guest user can read, anyone on the internet can read. Every public site runs unauthenticated visitors as a single guest user, and that user's profile, sharing rules, Apex classes and Flows decide what an anonymous request can reach. No password stands in the way.

In March 2026 Salesforce warned customers about a threat actor mass-scanning public Experience Cloud sites through the /s/sfsites/aura endpoint, using a modified version of the Aura Inspector auditing tool that extracted data instead of only reporting it. Salesforce said the issue "is not due to any vulnerability inherent to our platform": the exposure came from guest access that customers had configured too widely.

This is a concrete checklist for closing that gap, built on Salesforce's own recommended actions, followed by how Vulkro for Salesforce shows what a guest can actually reach.

AgentExchange Security Review: what fails, and how to pass the first time

· 8 min read
Vulkro
Security research

A failed AgentExchange (formerly AppExchange) Security Review rarely fails on something exotic. It fails on a query that skipped a field-level check, a class that forgot its sharing keyword, or a Visualforce page that printed a URL parameter as raw HTML. The fixes are usually small. The cost of finding them in the review instead of before it is not.

Three facts about that cost, stated carefully. Salesforce publishes no first-pass failure rate; about half is the figure partners cite most often for first submissions, and it is an industry estimate, not an official one. On a paid solution, Salesforce charges a $999 fee for the initial submission and for every later attempt, and a solution typically takes four to five weeks to get through review (Salesforce). Salesforce has since renamed it the AgentExchange Security Review. The weeks are spent in the queue; the way to save them is to find the issues while you develop.

With sharing vs without sharing in Apex, and inherited sharing

· 10 min read
Vulkro
Security research

With sharing vs without sharing is the first access question to ask of any Apex class. The keyword decides whether the class sees only the records the running user is allowed to see, or every record in the org. Get it wrong on a class a community user or a site guest can call and the result is not a bug report, it is a data exposure.

The rules are short, but there are three keywords, a default that changed with API version 67.0, and a few edge cases (inner classes, triggers, async jobs) where the answer is not obvious from reading the class header.

This post covers what with sharing, without sharing and inherited sharing each do, what happens when the keyword is left out, when without sharing is the right choice, how it combines with guest users, and why none of this replaces object and field permission checks.

Salesforce Flow security: system context, guests and Apex actions

· 10 min read
Vulkro
Security research

Salesforce Flow security gets less attention than Apex security, even though a Flow can read, create, update and delete records with exactly the same reach. A Flow running in system context without sharing has no idea who started it. If the person who started it was an anonymous visitor to a public site, the Flow still does what it was built to do, with access to all data.

Flows are also easier to ship than Apex: no code review or test class is required, and the access decision is one setting in Flow Builder.

This post covers the Flow run modes and their defaults, screen flows exposed to guest users, Flows started from Apex and Lightning components, record-triggered flows that move data where it should not go, and what Vulkro for Salesforce checks in Flow metadata.

Salesforce security audit: a repeatable method for consultancies

· 9 min read
Vulkro
Security research

A Salesforce security audit for a client is skilled work done with weak tools. The consultant knows what to look for: who holds Modify All Data, which classes a guest user can call, which connected app still has a refresh token from a vendor that left two years ago. But the method often lives in a spreadsheet and in the memory of whoever ran the last engagement. Two consultants auditing two orgs check different things, and the client cannot compare this year's report with last year's.

A repeatable method fixes that. The same scope, the same access, the same checks in the same order, and a report the client can hold you to. This post sets out the method we see work for Salesforce partners and consultancies, and where Vulkro for Salesforce fits into each step.

LWC security: five places Lightning Web Components go wrong

· 10 min read
Vulkro
Security research

LWC security is mostly a question of where a component steps outside the framework. A Lightning web component that renders values through its template, reads records through the platform and calls Apex that checks access is hard to break. The trouble starts at the edges: an innerHTML assignment, a lwc:dom="manual" container, an Apex method that trusts its caller, a jQuery copy from 2019 in a static resource, a message listener that never asks who sent the message.

Each of those is a small decision a developer makes on an ordinary afternoon. None of them looks dangerous in a pull request. This post walks through the five that matter most, with vulnerable and fixed code for each, and says plainly what static analysis can and cannot tell you about them.