Skip to main content

30 posts tagged with "Application security"

Code-level security beyond Salesforce, with Vulkro Core.

View All Tags

SSRF in Node.js: how a user-supplied URL reaches your cloud

· 10 min read
Vulkro
Security research

Server-side request forgery (SSRF) in Node.js usually starts with a helpful feature. A link preview, a webhook tester, an "import from URL" button, a PDF renderer that fetches images. The server takes a URL from the user and fetches it. The user picks the URL, but the request leaves from inside your network, with your server's reach.

That reach is the problem. From the outside an attacker cannot talk to your admin service on 10.0.3.7, your Redis on localhost, or the cloud metadata service at 169.254.169.254. Your server can, and an SSRF bug lets the attacker borrow it.

This post walks through the Node.js shapes of SSRF, the fixes that hold up (and the ones that do not), and what Vulkro checks in your code.

Supply-chain attacks are a code problem

· 9 min read
Vulkro
Security research

Supply-chain security is usually sold as a list problem: keep an inventory of your packages, match it against a vulnerability feed, patch what turns up. That works for the bug a maintainer shipped by accident. It did very little for the attacks of 2025, because in almost every one the malicious version was installed and running before any feed knew it existed.

The 2025 compromises were not vulnerabilities. They were programs. Each one read a credential, called a network endpoint, ran a shell command or republished itself, and each of those is a shape you can read in code without waiting for anyone to publish an advisory.

How to evaluate a SAST tool: a precision-first checklist

· 9 min read
Vulkro
Security research

Knowing how to evaluate a SAST tool matters more than any feature list, because the demo is the worst evidence you will get. A vendor demo runs on code chosen to show findings, usually a deliberately vulnerable app the tool has seen many times. Your code is different: older, larger, built on frameworks the demo never touched, and full of safe code that looks risky.

The real cost of a static analysis tool is not the licence. It is the hours your engineers spend deciding whether each finding is real. A tool that reports more findings is not better if most of them are wrong. This checklist is built around that: measure precision first, on your code, and ask the questions that a findings count hides.

OWASP API Security Top 10: what a source code scan can and cannot find

· 9 min read
Vulkro
Security research

The OWASP API Security Top 10 is the list most teams reach for when someone asks "is our API secure?". The 2023 edition has ten items, from broken object level authorization to unsafe consumption of third-party APIs. It is a good list. It is also a mix of very different kinds of problem, and no single tool sees all of them.

Some items are visible in the code that handles a request: a lookup with no ownership predicate, a URL fetched straight from the body. Some are partly in code and partly in the gateway, the CDN and the deployment. And some are about what your business would lose if a flow were automated, which no parser can read.

This post goes through all ten and says plainly which a source code scan can find, which it can only hint at, and what Vulkro checks for each.

Your database schema is a security document

· 8 min read
Vulkro
Security research

Ask a team where their application keeps personal data and you usually get an answer about systems: the main database, the analytics warehouse, the logging stack. Ask which columns, and which endpoints write them, and the answer gets vague. Yet that information is already written down, precisely, in the repository. Every ORM model and every migration is a statement about what the application stores and how.

That makes the schema one of the most useful security documents a team has, and one of the least read. A password column next to a create() call that never hashes. A users.email that is used to sign in but is not unique. An api_token stored as it was issued. These are not subtle bugs, and the schema shows them plainly once someone looks.

IDOR prevention in Express and NestJS: ownership checks that hold

· 9 min read
Vulkro
Security research

IDOR prevention comes down to one question asked on every request: is this record yours? An insecure direct object reference (IDOR) is what happens when the server asks only whether you are logged in. You request invoice 8812, the server checks your session, loads invoice 8812 and returns it. Whose invoice it was never came up.

OWASP ranks this first in the API Security Top 10 (2023) as broken object level authorization (BOLA), and its prevention advice is blunt: check that the logged-in user may act on the record every time client input picks the record. We covered the breaches in broken access control is still number one. This post is about the code: how to make that check structural in Express and NestJS with Prisma, and how to test that it stays there.

The attacks of 2025, and the checks that flag their root causes

· 12 min read
Vulkro
Security research

Most of the attacks that made the news in 2025 did not need anything clever. A package version that should not have been installed. An install script that read a token and sent it somewhere. An API that returned whichever record you asked for. A prompt template that read a field anyone on the internet could write. Each one ended in a headline, and each one started as a line of code or configuration that a check could have pointed at.

This post goes through twelve of them, from late 2024 to early 2026. For each: what happened, as the public source describes it, the weakness underneath, and the Vulkro check that flags that weakness. Every check id below is in the shipped catalogue, and the core of each mapping was run against a small reproduction of the weakness before it was written down.

Imported is not reachable

· 7 min read
Vulkro
Security research

Most dependency alerts answer one question: is a vulnerable version of this module listed in your manifest? That is a useful question, and a blunt one. A module is a big thing. An advisory is usually about one function inside it, sometimes two or three. Whether your program ever calls that function is a different question, and for triage it is the one that matters.

Go is the ecosystem where that second question is easiest to ask, because the Go vulnerability database writes the answer key into every record: the package and the exact symbols that contain the bug. This post walks through what that data looks like, the three answers Vulkro now gives for each Go advisory, and what those answers can and cannot tell you.

Next.js server actions are public endpoints

· 9 min read
Vulkro
Security research

A server action looks like a function call. You put 'use server' at the top of a file, export an async function and pass it to a form or a button. There is no route file, no fetch and no URL to think about. That is the appeal, and it is also the trap.

Every server action is an HTTP endpoint. The browser calls it with a POST request that names the action, and the server runs your function with whatever arguments that request carries. The Next.js data security guide says an exported action is reachable "via a direct POST request, not just through your application's UI." Anyone who can send a POST can call it, with arguments they choose.

So every action has to answer the questions every API endpoint answers: who is calling, and may they do this to this record?

Security analysis without wasting tokens

· 9 min read
Vulkro
Security research

Ask an AI coding agent to "check this repository for security issues" and watch what it does. It lists the tree. It opens the route files, then the middleware, then the database layer, then a few helpers it was not sure about. Each file goes into its context window. By the time it has an opinion about one endpoint, it has paid to read forty files that had nothing to say.

That is not a flaw in the agent. It is the only way a model can look for a vulnerability on its own: by reading. And reading a codebase is the most expensive thing you can ask a model to do.

One engine for Salesforce and the rest of your stack

· 7 min read
Vulkro
Security research

A Salesforce org rarely stands alone. Around it there is usually a small fleet of services nobody thinks of as "the Salesforce project": a Node service that receives webhooks and writes them into the org, a Python job that copies records into a warehouse, a Go API behind the customer portal, a Java service that holds the integration credentials. They are written by different teams, deployed by different pipelines and reviewed, if at all, by different tools.

An attacker does not see that boundary. If the first hop of the path is a route in the Node service and the last hop is a field in the org, a review that looks at only one side sees half a path and calls it two unrelated medium findings.

A clean scan that did not read your code is not a clean scan

· 8 min read
Vulkro
Security research

A security scan finishes, prints zero findings and exits 0. The pipeline goes green and the pull request merges. Two very different situations produce exactly that output. In the first, the scanner read every file and found nothing worth reporting. In the second, it read a fraction of the project, found nothing in that fraction, and said nothing about the rest.

From the outside the two look identical. That is the problem. An empty result is only evidence of safety if you know what the scanner actually looked at, and most scan output does not say.

This is not a bug in any one tool. It is what happens when a scanner meets a language it does not support, a file it cannot parse, or an analysis pass that does not finish, and its output has nowhere to put that fact.