How you actually fix it.
The recurring vulnerability classes in medical devices, each with the prescriptive remediation: before and after source code, the software, firmware and hardware changes, and the design requirements that keep it from happening again.
Written for the people who build the device. Every entry is how you would fix the class in your own product, at source level, not how an operator mitigates it in the field.
Every entry is prescribed from public reporting on medical device vulnerabilities, drawn from advisories and the trade press and linked to the news coverage that prompted it. Nothing here is derived from customer engagements, private assessments, or any product ELTON has tested. The vulnerabilities are examples of a general issue class. The remediation is how a manufacturer resolves that class in their own product, with current software, firmware, hardware, and network hardening.
Hard-coded and Default Credentials
A single secret ships inside every unit, or a device arrives usable on a documented default login. Whoever recovers that one credential, from a firmware dump, a shared APK, or the manual, holds the same access on the entire fleet. For a medical device this is not a password problem, it is a fleet-wide access problem, because the value never changes and the attacker only has to learn it once.
As the manufacturer, delete the shared secret from every shipped artifact, provision a unique identity per unit at manufacture, and verify credentials server-side against a slow hash. If a secret was ever compiled in, treat it as public and rotate.
// Vulnerable: one key in every shipped image
static const uint8_t DEVICE_KEY[16] = {
0x2f,0xa1,0x77,0x0c,0x9b,0x34,0xee,0x51,
0x8d,0x40,0x12,0xbc,0x6a,0x99,0x03,0xd7 };
bool auth(const uint8_t *presented) {
return memcmp(presented, DEVICE_KEY, 16) == 0;
}
// Hardened: unique key provisioned into a secure element,
// never present in the firmware image
bool auth(const uint8_t *presented) {
uint8_t key[16];
if (!se_read_key(SE_SLOT_DEVICE_ID, key)) return false;
bool ok = ct_memcmp(presented, key, 16) == 0; // constant-time
secure_zero(key, sizeof key);
return ok;
}
- Make first-use setup require changing any default before the device becomes operational. A device that runs on its shipped default is a design defect, not an operator error.
- Write a requirement that no secret is identical across two units, and add a manufacturing test that fails a build carrying a shared credential.
- Treat "extractable from a distributed artifact" as the threat model for every secret, and design so extraction yields nothing reusable.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Missing Authentication on Wireless Control
A device accepts control commands over Bluetooth Low Energy from any peer in radio range, with no pairing check and no authentication on the characteristics that change device behavior. For a stimulator, a wearable, or a mobility device, that means an attacker standing nearby can alter output, rewrite readings, or move the device. Physical proximity is the whole cost of entry, and a clinical space is full of strangers.
As the manufacturer, gate every writable characteristic behind an authenticated, bonded session on the device itself, strip undocumented command handlers from production builds, and default to a safe state on anything unauthenticated.
// Vulnerable: any peer in range can set stimulation output
int on_write(conn_t *c, uint16_t handle, const uint8_t *v, int n) {
if (handle == HANDLE_STIM_LEVEL)
set_stim_level(v[0]); // no auth, no bonding check
return 0;
}
// Hardened: state-changing writes require an encrypted, bonded link
int on_write(conn_t *c, uint16_t handle, const uint8_t *v, int n) {
if (handle == HANDLE_STIM_LEVEL) {
if (!c->encrypted || !c->bonded || !c->authenticated)
return BLE_ERR_INSUFFICIENT_AUTHENTICATION;
if (!stim_level_in_safe_range(v[0])) return BLE_ERR_VALUE;
set_stim_level(v[0]);
}
return 0;
}
- Write a requirement that every state-changing command requires an authenticated session, and enumerate the safety-critical commands explicitly in the threat model.
- Design the safe state: on an unexpected or unauthenticated command, the device holds or reverts to a defined safe condition rather than acting.
- Ban undocumented command paths by policy and test for their absence, because a hidden handler is an unauthenticated handler.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Broken Cloud and API Authentication
The device is fine, the backend is the problem. A cloud login endpoint returns a session token on a value it never actually verified, or a control-plane API exposes a critical function with no authentication at all. The connected device has moved most of its real attack surface to a server the manufacturer also owns, and that server decides who gets in.
As the manufacturer, verify the password against a stored hash before issuing a token, put every state-changing endpoint behind an authorization check tied to the caller, and rate-limit. Assume any account reachable before the fix was reached.
// Vulnerable: any well-formed password returns a valid session
app.post("/login", async (req, res) => {
const { email, password } = req.body;
if (email && looksLikePassword(password)) {
return res.json({ token: sign({ email }) });
}
res.status(400).end();
});
// Hardened: verify against a stored hash, throttle, scope the token
app.post("/login", rateLimit(), async (req, res) => {
const { email, password } = req.body;
const user = await users.byEmail(email);
if (!user || !(await argon2.verify(user.hash, password)))
return res.status(401).json({ error: "invalid_credentials" });
res.json({ token: sign({ sub: user.id, role: user.role },
{ expiresIn: "15m" }) });
});
- Write the requirement that authentication is enforced server-side on every endpoint, and that no endpoint trusts a client assertion of identity or role.
- Model the backend as in-scope for device security, because for a connected device it is the device. Test the API with the same rigor as the firmware.
- Design tokens to be short-lived, bound to session context, and revocable, so a single leak does not become standing access.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Medical Image Parser Memory Safety
A viewer or server takes a crafted image file and the parser writes or reads outside its buffer, a heap overflow or an out-of-bounds access that can crash the process or run code. In imaging the file arrives from outside your own systems constantly, on media and across referrals, so the compressed pixel path inside a medical image container is attacker-controlled input, and it keeps proving it.
As the manufacturer, validate every length and offset from the file against the real buffer before you copy, decode in a sandboxed least-privilege process, and fuzz the path continuously so the next bug is yours to find.
// Vulnerable: frame length comes from the file, copied blindly
void load_pixels(img_t *img, const uint8_t *file, size_t flen) {
uint32_t declared = read_u32(file + OFF_LEN);
memcpy(img->heap, file + OFF_DATA, declared); // heap overflow
}
// Hardened: validate declared length against both buffers first
int load_pixels(img_t *img, const uint8_t *file, size_t flen) {
if (flen < OFF_DATA) return ERR_TRUNCATED;
uint32_t declared = read_u32(file + OFF_LEN);
size_t avail = flen - OFF_DATA;
if (declared > avail || declared > img->cap)
return ERR_BOUNDS; // reject, do not copy
memcpy(img->heap, file + OFF_DATA, declared);
return OK;
}
- Require continuous fuzzing of every file-format parser as a release gate, with malformed-input corpora, not a one-time test.
- Design the parser to fail closed and contained: a bad file produces a handled error in an isolated process, never a corrupted heap in a privileged one.
- Track every embedded decoder in the SBOM so an upstream parser advisory maps to your products in minutes.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
SQL Injection in Clinical Databases
User input reaches the database as part of the query string, so an attacker who controls the input controls the SQL. At the top of the scale this is unauthenticated and remote, which means anyone who can reach the endpoint runs arbitrary SQL against a database holding patient and clinician records. It is one of the oldest classes in the catalogue, and it still lands maximum-severity ratings on medical products.
As the manufacturer, parameterize every query so input is never concatenated into SQL, run the app on a least-privilege database account, and enforce it with a static-analysis gate so a concatenated query fails the build.
# Vulnerable: patient_id is concatenated straight into SQL
def get_patient(conn, patient_id):
q = "SELECT * FROM patients WHERE id = '%s'" % patient_id
return conn.execute(q).fetchone()
# Hardened: parameter is bound, never part of the statement text
def get_patient(conn, patient_id):
q = "SELECT * FROM patients WHERE id = %s"
return conn.execute(q, (patient_id,)).fetchone()
- Require parameterized data access as a coding standard, enforced by static analysis in CI/CD so a concatenated query fails the build.
- Design authorization to sit in front of every data path, so even a working injection is bounded by the caller identity and role.
- Include injection test cases traced to every input in the threat model, so absence of findings is proven, not assumed.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Cleartext and Unencrypted Transport
The product can encrypt its traffic but does not by default, or a portal transmits credentials in the clear. Anyone positioned on the network path reads database traffic, login details, or patient data as it passes. The capability existed. The default undid it, and a legacy deployment quietly kept passing plaintext for years.
As the manufacturer, make transport security the default and the only option, refuse to negotiate down to plaintext, and validate the certificate on the device rather than trusting the network.
# Vulnerable: falls back to plaintext, does not verify the peer
sock = socket.create_connection((host, port))
if server_offers_tls:
sock = ssl.wrap_socket(sock) # no cert verification
send_credentials(sock, user, password)
# Hardened: TLS required, certificate verified, no downgrade
ctx = ssl.create_default_context(cafile=PINNED_CA)
ctx.check_hostname = True
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
sock = ctx.wrap_socket(socket.create_connection((host, port)),
server_hostname=host)
send_credentials(sock, user, password)
- Ship secure by default. Encryption an operator has to know to enable is encryption most deployments will not have.
- Write a requirement that no credential or patient datum is ever transmitted without transport encryption, and test for downgrade paths.
- Design out the legacy plaintext mode on a defined timeline rather than carrying it indefinitely as a compatibility option.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Unrestricted File Upload
A server accepts an uploaded file without constraining what it is or where it lands, and the file can then be executed. On an imaging archive or a management server this is a short path from a web request to code running on the box that holds the studies. The upload feature was meant for data. It became a way in.
As the manufacturer, validate type by content, store uploads under a server-generated name in a non-executable location outside the web root, and serve them back through a handler that never interprets them.
// Vulnerable: attacker-named file lands in the web root, executable
app.post("/upload", (req, res) => {
const f = req.files.study;
f.mv("./public/uploads/" + f.name); // e.g. shell.php
res.send("ok");
});
// Hardened: validated type, random name, no-exec dir off the web root
app.post("/upload", (req, res) => {
const f = req.files.study;
if (!DICOM_MAGIC.equals(f.data.subarray(128, 132)))
return res.status(415).json({ error: "unsupported_type" });
const name = crypto.randomUUID() + ".dcm";
fs.writeFileSync(path.join(UPLOAD_DIR_NOEXEC, name), f.data);
res.json({ id: name });
});
- Require that no user-supplied file is ever stored in an executable location, as a design invariant checked in review.
- Design uploads to be inert data by construction, decoupled from any code path that could interpret them.
- Model the file-upload endpoint as a primary attack surface on any server that holds clinical data, and test it as one.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Insecure Deserialization
The product turns untrusted bytes back into objects without constraining what those bytes are allowed to become, and a crafted payload becomes code execution. Left on a permissive setting, a remoting port or a stored blob is a direct path in. The device trusted its input the moment it deserialized it.
As the manufacturer, stop deserializing untrusted data into arbitrary types. Move to a schema-validated format across trust boundaries, and where a framework exposes a type filter, set it to the most restrictive value.
// Vulnerable: Full lets a crafted payload instantiate arbitrary types
var prov = new BinaryServerFormatterSinkProvider {
TypeFilterLevel = TypeFilterLevel.Full
};
ChannelServices.RegisterChannel(new TcpChannel(props, null, prov),
ensureSecurity: false);
// Hardened: Low type filter, TLS, authentication required
var prov = new BinaryServerFormatterSinkProvider {
TypeFilterLevel = TypeFilterLevel.Low
};
ChannelServices.RegisterChannel(new TcpChannel(secureProps, null, prov),
ensureSecurity: true);
// Better still: replace remoting with an authenticated,
// schema-validated HTTPS endpoint.
- Write the requirement that no data crossing a trust boundary is deserialized into arbitrary types, and enumerate every such boundary.
- Design data exchange around validated schemas rather than native object serialization.
- Encrypt and integrity-check data at rest so a stored blob cannot be swapped for a hostile one.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Insecure Update Channels
The updater does not verify who it is talking to or what it is installing, so a man in the middle can deliver a malicious update. The one mechanism meant to fix the device becomes the cleanest way to compromise it, at scale, because every unit trusts it.
As the manufacturer, verify the server certificate on the update connection and verify a cryptographic signature on the payload against a key provisioned on the device before anything is written. Transport and payload signing are separate controls, and you need both.
// Vulnerable: whatever the server sent gets written and booted
int apply_update(const char *url) {
buf_t img = http_get(url); // no cert check
flash_write(PARTITION_APP, img.data, img.len);
reboot();
}
// Hardened: verify signature against a provisioned key before flashing
int apply_update(const char *url) {
buf_t img = https_get_verified(url); // pinned CA, chain checked
if (img.len == 0) return ERR_TRANSPORT;
if (!ed25519_verify(img.sig, img.data, img.len, se_pubkey()))
return ERR_BAD_SIGNATURE; // refuse unsigned/tampered
if (img.version <= current_version()) return ERR_ROLLBACK;
flash_write(PARTITION_APP, img.data, img.len);
reboot();
}
- Require signed updates with on-device signature verification as a non-negotiable property of any device that can update in the field.
- Design the update path to fail closed: an unverified payload is never installed, even partially.
- Include rollback protection so an attacker cannot force a return to a known-vulnerable version.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Weak Credential Storage and Shared Keys
Passwords are stored with encoding that can be reversed, or the whole product line is built on one cryptographic key identical across every install. Recover the key or the store once and you have every deployment, and often a token that can simply be replayed to walk past authentication. The cryptography was present. It was just not doing any work.
As the manufacturer, hash credentials with a purpose-built password algorithm, derive keys uniquely per installation, and bind tokens so a captured one cannot be replayed. Assume anything protected the weak way is already recovered.
# Vulnerable: base64 is encoding, not hashing; trivially reversed
def store(user, password):
db.save(user, base64.b64encode(password.encode()))
def check(user, password):
return db.load(user) == base64.b64encode(password.encode())
# Hardened: argon2id, per-record salt, constant-time verify
ph = argon2.PasswordHasher()
def store(user, password):
db.save(user, ph.hash(password)) # salt + params embedded
def check(user, password):
try:
return ph.verify(db.load(user), password)
except argon2.exceptions.VerifyMismatchError:
return False
- Require per-installation key derivation, and ban any secret identical across two deployments.
- Design tokens to be single-use or context-bound so interception does not equal access.
- Write the requirement that stored credentials are irreversible by construction, and test that the store yields nothing usable if it leaks.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Insecure Defaults
The product exposes an interface with authentication switched off out of the box, so an operator who does not know to turn it on runs it open. Reachable records, no login required, and nobody made a mistake except the default. Security that depends on an operator knowing to enable it is security most deployments will not have.
As the manufacturer, make the default configuration the secure configuration. Require an admin credential before any interface serves data, and refuse to expose anything until setup is complete.
# Vulnerable: default config exposes the HTTP API with no auth
http:
bind: 0.0.0.0:8042
authentication_enabled: false
remote_access_allowed: true
# Hardened: auth required; server refuses to start open
http:
bind: 0.0.0.0:8042
authentication_enabled: true # cannot be false in production
remote_access_allowed: false # opt in per deployment
require_admin_setup_on_first_boot: true
- Write the requirement that the default configuration is the secure configuration, and that no shipped default exposes data without authentication.
- Design first-run setup to force the security-relevant choices before the device is usable.
- Test the out-of-box state as a threat model in its own right, because that is the state many units will stay in.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Local Access and Privilege Escalation
A standard user on the workstation becomes SYSTEM, usually through a library loaded from a path the user can write, or the client simply hands over credentials it stored where local access can reach them. The attacker is already on the box, as staff or through a foothold, and the software turns limited access into full control of the imaging station.
As the manufacturer, load libraries only from fixed trusted paths, hold short-lived tokens instead of recoverable credentials on the client, and remove user-writable directories from any privileged service search path.
// Vulnerable: resolves ccsvc.dll via the search path,
// which includes a user-writable working directory
HMODULE h = LoadLibraryA("ccsvc.dll");
// Hardened: restrict the search path, load by absolute path only
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
HMODULE h = LoadLibraryExW(L"C\\Program Files\\Vendor\\ccsvc.dll",
NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
// installer sets the app dir ACL so standard users cannot write it
- Require pinned, absolute library load paths as a build standard, and retire unsupported third-party SDKs that reintroduce the flaw.
- Design the client to hold nothing an attacker with local access can reuse: tokens, not passwords, and nothing recoverable at rest.
- Set installer ACLs so no privileged binary loads from a user-writable location.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Broken Access Control and Enumeration
An authenticated but low-privilege user changes a parameter and reaches records outside their role, or an endpoint answers differently for real and fake accounts so an attacker can enumerate who exists, or a backend simply returns its own internals to anyone who asks. The login worked. The authorization did not follow through on every object the request could name.
As the manufacturer, authorize every object reference on the server against the caller, return uniform responses so nothing can be enumerated, and strip internal detail from what the backend hands back.
// Vulnerable: any authenticated user reads any study by id (IDOR)
app.get("/study/:id", auth, async (req, res) => {
const study = await studies.byId(req.params.id);
res.json(study);
});
// Hardened: authorize the specific object against the caller
app.get("/study/:id", auth, async (req, res) => {
const study = await studies.byId(req.params.id);
if (!study || !canAccess(req.user, study))
return res.status(404).end(); // same answer, no oracle
res.json(study);
});
- Write the requirement that authorization is checked per object reference, and include object-reference tampering (IDOR) in the test plan explicitly.
- Design endpoints to be uniform and quiet: no oracle in the response, no internal state in the error.
- Model information disclosure as a finding class in its own right, because leaked internals are the map for the next attack.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Denial of Service via Unvalidated Input
A malformed or excessive input pushes the service over, a null-pointer dereference or an unbounded operation, and on a central monitor or a monitoring API that means the screen clinicians rely on goes dark. Availability is a safety property here. A crash is not just downtime, it is the aggregation point for bedside vitals dropping out.
As the manufacturer, validate and bound every input at the boundary, handle malformed messages as a defined error path rather than dereferencing them, and watchdog the clinical display so a fault recovers to a safe view.
// Vulnerable: a message with no waveform crashes the station
void on_msg(const msg_t *m) {
render_waveform(m->wave->samples, m->wave->count); // m->wave may be NULL
}
// Hardened: validate structure and bounds, fail safe on bad input
void on_msg(const msg_t *m) {
if (!m || !m->wave) { log_drop("no waveform"); return; }
if (m->wave->count == 0 || m->wave->count > MAX_SAMPLES) {
log_drop("bad sample count"); return;
}
render_waveform(m->wave->samples, m->wave->count);
}
- Treat availability as a safety requirement for any device clinicians watch, and design the safe degraded state explicitly.
- Require input validation and resource bounds on every external interface as a coding standard.
- Include malformed-input and load test cases in verification, because the crash is the finding.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Client-Side Injection
Field-entered data is reflected into a WebView or web page without encoding, so input becomes script that runs in the app context. On a mobile app carrying patient records collected in the field, that script reaches the PHI the app holds. The app treated data as display and got code.
As the manufacturer, context-encode every value before it renders, set a strict content security policy so injected script has nothing to run, and prefer native rendering for sensitive data.
// Vulnerable: field note is parsed as HTML and can carry script
noteEl.innerHTML = patient.note; // <img src=x onerror=steal()>
// Hardened: render as text, and set a strict CSP header/meta
noteEl.textContent = patient.note; // never parsed as markup
// Content-Security-Policy: default-src 'self'; script-src 'self';
// object-src 'none'; base-uri 'none'
- Require output encoding at every sink as a coding standard, enforced in review and static analysis.
- Design a content security policy as a hard boundary, so a missed encode is still contained.
- Include injection test cases for every field that reaches a rendering surface.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Data and Output Integrity
The software does not verify the integrity of its own output, so a tampered result passes as genuine. When that output is a diagnostic or forensic result, a silent change is worse than a crash, because nobody sees it. The system produced the right-looking file and could not tell it had been altered.
As the manufacturer, sign results at creation with a device-held key and verify the signature before anything consumes them, and lock down who can write the result store.
# Vulnerable: result is trusted with no integrity check
def save_result(run_id, data):
store.write(run_id, data)
def load_result(run_id):
return store.read(run_id) # tampering is invisible
# Hardened: sign on write, verify on read, key in secure element
def save_result(run_id, data):
sig = se_sign(data) # private key never leaves the SE
store.write(run_id, data, sig)
def load_result(run_id):
data, sig = store.read(run_id)
if not se_verify(data, sig):
raise IntegrityError(run_id) # refuse a tampered result
return data
- Require integrity verification on any output that carries clinical or legal weight, as a design property rather than an add-on.
- Design an audit trail that makes every change to a result attributable and visible.
- Model tampering, not just theft, as a threat to data, because integrity failures do not announce themselves.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Supply Chain and SBOM Exposure
The advisory is not for a bug you wrote. It is in a library, a toolkit, or a platform your product embeds, and there are a lot of them. Most of a connected device is code someone else maintains, which means most of its vulnerability exposure lives in the supply chain. The question a reviewer and an attacker both ask is the same: when the upstream bug drops, are you affected, and how fast can you say so.
As the manufacturer, pin dependencies to fixed versions, generate an SBOM on every build including transitive components, and gate the pipeline on known-vulnerable components so an advisory maps to your products automatically.
# Vulnerable: floating range, no SBOM, no gate
dependencies:
gdcm: "^3.0" # resolves to whatever is latest at build
build:
steps: [ compile, package ]
# Hardened: pinned version, SBOM emitted, pipeline fails on advisories
dependencies:
gdcm: "3.0.24" # exact, reviewed, reproducible
build:
steps:
- compile
- sbom: cyclonedx --output sbom.json
- gate: vuln-scan sbom.json --fail-on high # blocks the release
- package
- Require a live SBOM as a release artifact, answerable in minutes, not a one-time export filed with the submission.
- Design the patch-delivery path for third-party and platform components as a first-class capability of the product.
- Monitor the components you depend on with the same rigor as first-party code, because to an attacker there is no difference.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Embedded OS and Legacy Lifecycle
The vulnerability is in the operating system inside the controller, or in a server behind the device, or in a system that went end of service years ago and still runs in the field. Regulators have classified actions here on potential harm alone, no attacker required. A device that can no longer be patched is a standing liability, and the fleet outlives the support that was meant to secure it.
As the manufacturer, own the embedded OS and server lifecycle as a safety obligation, design controllers to update in the field, and make every fault degrade to a defined safe state rather than an unexpected stop.
// Vulnerable: an unhandled fault simply halts the pump
void on_fault(fault_t f) {
halt(); // pump stops with no defined safe behavior
}
// Hardened: faults drive a defined, clinically safe state
void on_fault(fault_t f) {
enter_safe_state(); // hold flow, alarm, keep telemetry
raise_alarm(ALARM_TECHNICAL, f);
if (!attempt_safe_recovery(f))
maintain_safe_state_until_service();
}
- Treat embedded-OS currency on a life-sustaining or clinical controller as a safety requirement, with an owner and a schedule.
- Design the safe failure state so a fault never becomes an unexpected stop on a device a patient depends on.
- Plan device lifecycle to a defined end, because a system that outlives its security support is a liability you scheduled.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
Exposed Hardware Debug Interfaces
A production device ships with a debug interface, JTAG or similar, live and reachable, often alongside embedded secrets and unencrypted links. The interface that made development possible becomes the one that makes extraction and control possible, and on a life-sustaining device that is a safety problem, not just a security one. A maximum-severity rating on a ventilator is what an exposed debug port looks like in the field.
As the manufacturer, disable or fuse-lock the debug interface before the device ships, provision unique secrets rather than embedded ones, encrypt every link, and authenticate the paths that change device behavior.
// Vulnerable: debug access left enabled in the field
void board_init(void) {
clocks_init();
// JTAG/SWD remain enabled; no fuse burned
}
// Hardened: production image locks debug on first secure boot
void board_init(void) {
clocks_init();
if (fuse_get(FUSE_DEBUG_LOCK) == 0) {
fuse_blow(FUSE_DEBUG_LOCK); // permanent, one-time
}
debug_port_disable(); // belt and suspenders
}
- Require debug interfaces to be disabled or fuse-locked in production as a manufacturing gate, verified per unit.
- Write the requirement that no production device carries an embedded shared secret or an unauthenticated control path.
- Model the hardware attack surface, not just the software one, for any device where physical or proximate access is realistic.
ELTON does not stop at naming the class. It proves which findings are exploitable on the real product, then prescribes the specific remediation down to the code fix, delivered as a ticket or over ELTON MCP. Prescription, not a list of possibilities, is the difference between this library and a consultant’s report.
ELTON prescribes the fix. A consultant hands you a list.
See the ELTON Fix →