ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Application Security and DevSecOps

How application security controls actually work inside a delivery pipeline: SAST, DAST, SCA, secret scanning, supply-chain provenance, triage by reachability, and the failure modes that turn a security program into noise.

Application security (AppSec) is the practice of finding and preventing the defects in software that an attacker can convert into access, and DevSecOps is the delivery discipline that puts those checks where engineers already work — in the pull request, the build, and the deploy — instead of in a review that arrives after the code has shipped.

The hard part is not choosing scanners. It is deciding which findings stop a release, who owns each fix, and how a control behaves when it is wrong. A program that flags everything and blocks nothing is operationally indistinguishable from having no program at all, and it is more expensive.


What AppSec Covers

Four distinct surfaces get lumped under one word, and they fail for different reasons:

  • Code you wrote — injection into an interpreter or query, broken authorization logic, unsafe deserialization, server-side request forgery, credentials committed to the repository.
  • Code you imported — direct and transitive dependencies, base images, build plugins. You did not write it, you did not review it, and it runs with your process privileges.
  • The way it is built and delivered — the build system, its credentials, the artifact registry, and the deploy path. This is production infrastructure regardless of what the org chart says.
  • The runtime configuration — the container, the cloud role attached to it, what is exposed to the internet, and the response headers the application actually sends.

Tools are strong on the second and fourth surfaces and weak on the first, because business-logic authorization flaws depend on intent that a scanner cannot read. A missing ownership check between two tenants looks exactly like correct code. That gap is why threat modeling and design review stay necessary no matter how many scanners run.


The Scanner Toolchain

ControlWhat it inspectsWhat it is good atWhere it is blind
SASTSource, AST, data flowTainted input reaching a dangerous sink; unsafe API useIntent and authorization; anything crossing a process boundary; frameworks it does not model, which produce noise
SCAManifests and lockfilesKnown-vulnerable dependency versions, licence obligationsVendored or unpinned code; whether the vulnerable function is reachable from your code at all
DASTA running instance over HTTPMisconfiguration, missing headers, behaviour that only appears at runtimeAnything behind an authentication flow it cannot complete; deep state; it also mutates data, so it needs a disposable environment
IASTInstrumented runtimeConfirming exploitability along requests actually exercisedPaths your tests never hit; runtime overhead
Secret scanningDiffs and full historyCredentials committed to sourceSecrets leaked outside the repository; and detection does not rotate anything
IaC / manifest policyTerraform, Kubernetes, cloud templatesPublic storage, permissive network rules, privileged containersDrift introduced after apply, or resources created outside the pipeline
Image scanningOS and language packages in a built imageInherited base-image vulnerabilitiesYour own application logic

Each control has a characteristic wrong answer. SAST over-reports, DAST under-reports, SCA reports accurately about a package and says nothing about your exposure. Choose the blocking gate based on which wrong answer you can live with.


Software Supply Chain

Pin dependencies and commit a lockfile. Without one, the same source builds differently on different days, and no statement about what you shipped can be verified afterwards. Most of the dependency risk lives in the transitive graph, not the handful of packages a developer typed.

Beyond pinning, three mechanisms matter. Provenance links a deployed artifact back to the commit and the builder that produced it, so “is this the code we reviewed?” is a verifiable question rather than an assumption. Signing and verification at admission gives that link teeth: if the deploy path refuses unsigned artifacts, an attacker who can push an image still cannot get it run. An inventory — an SBOM or an equivalent queryable index — is a response tool, not a prevention tool; its value is answering “where do we run this package?” in minutes instead of by grepping every repository in the middle of an incident.

Treat the build system as production. CI holds deploy credentials and signing keys, which makes a build step the highest-privilege code in the estate. Do not run untrusted pull-request code in a job that has access to those secrets; split the untrusted test job from the trusted build job, and scope build credentials to one repository and one destination.


Placing Controls in the Pipeline

Placement decides whether a control is useful or merely present. Early checks must be fast and mostly advisory; late checks must be few and genuinely blocking.

developer workstation
  └── pre-commit ......... secret scan, formatter        [fast, advisory]
        │
        ▼
pull request
  ├── SAST (changed files) ............................. [blocking on NEW findings]
  ├── SCA on the lockfile .............................. [blocking on NEW findings]
  ├── IaC / manifest policy ............................ [blocking]
  └── secret scan on the full diff ..................... [blocking, always]
        │
        ▼
build
  ├── produce ONE artifact (image / bundle / package)
  ├── scan THAT artifact, not the repo ................. [blocking on base-image CVEs]
  └── sign it + emit provenance (artifact ← commit ← builder)
        │
        ▼
pre-deploy
  ├── verify signature + provenance ⇒ refuse unsigned ... [blocking]
  └── DAST against a deployed staging copy ............. [advisory, scheduled]
        │
        ▼
runtime
  ├── config + exposure checks (headers, auth, network)
  ├── dependency inventory query when a new CVE lands
  └── logs and alerts routed to the OWNING team

The single most common structural mistake is scanning the repository and deploying something else — a different tag, a rebuilt image, a branch that drifted. Scan the artifact you deploy, and make the deploy refuse artifacts that were not scanned.


Triage and Reachability

A severity score describes a vulnerability in the abstract. It does not describe your exposure. Convert a finding into a decision with four questions, in this order:

  • Is the vulnerable code reachable from any of our entry points? A vulnerability in a code path we never call is inventory, not risk.
  • Does untrusted input reach it? Reachable from an authenticated admin console is a different problem from reachable from an unauthenticated endpoint.
  • Is there a compensating control already in the path — a network boundary, an authorization check, a parser that rejects the shape required to exploit it?
  • Is there a fixed version, and what does upgrading break? If the answer is a major version bump across a framework, that is a project, and it needs to be scheduled as one rather than left open as a ticket.

Set remediation windows per severity that your team can actually meet with its real capacity. A deadline nobody meets teaches everyone that deadlines here are fictional, which is worse than a longer window that holds. Every exception needs a named owner and an expiry date; an exception with neither is a silent decision to accept the risk forever.


Failure Modes

Anti-patternWhat it producesFix
Turn a scanner on and block on day oneA wall of pre-existing findings, then mass bypass and a disabled gateRun advisory first, then block only on findings new to the change — a ratchet, not a wall
Baseline the entire backlog as acceptedThe backlog never shrinks and nobody remembers whyBlock net-new, and burn the baseline down on an owned schedule
Findings routed to a security inboxThe people who can fix the code never see itRoute to the owning team in the tracker they already use, with the file and the line
Secret detected, access revoked laterThe credential is already out; removing the commit changes nothingTreat detection as a confirmed leak: rotate first, then clean history
No in-tool suppression pathSuppression happens in people’s heads and the tool is ignoredMake suppression explicit, reviewable, and expiring
Scanning source but shipping a different artifactClean reports that do not describe productionScan and sign one artifact and verify it at admission
Coverage measured by number of toolsOverlapping tools, no owner, no reduction in riskMeasure by surface covered and by time-to-fix, not by tool count

When Not to Add a Control

Adding a gate is not free: it costs build minutes, review attention, and credibility every time it is wrong. Skip a control when nobody will own its output, when an existing blocking gate already catches the same class, or when the component has no untrusted input path and the budget would do more good on the one that does. If you decline a control deliberately, write down why — an undocumented decision is indistinguishable from an oversight when someone audits it later, and compliance work will ask.

The inverse also holds. Controls that are cheap, quiet, and almost never wrong — secret scanning, dependency pinning, signature verification at deploy — should simply be on everywhere, with no exception process worth the name.


Checklist

  • Every repository has a named owning team, reachable from a finding
  • Secret scanning runs on every diff, and detection triggers rotation, not just removal
  • Dependencies pinned, lockfiles committed, transitive graph visible
  • The artifact that is scanned is the artifact that is deployed
  • Deploy path verifies signature and provenance, and refuses what it cannot verify
  • Build jobs holding credentials never execute untrusted contributor code
  • Gates block on new findings; the legacy baseline has a burn-down owner
  • Exceptions carry an owner and an expiry date
  • A dependency inventory can answer “where do we run X?” without a code search
  • Authorization logic is reviewed by humans, because no scanner reads intent

Related reading in this section: identity and access management decides who the request belongs to, zero trust architecture decides whether it is allowed to reach the service at all, threat modeling finds the design flaws scanners cannot, and compliance engineering turns these controls into evidence. For credential handling in the delivery path see secrets management, and for the section index see Security & Compliance.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →