You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'd like to propose a small, dependency-free enhancement: a config setting that lets IBC obtain the password by running a user-specified command at login time, instead of reading a literal value. One mechanism, platform-neutral in IBC itself — the command supplies the platform specifics:
IbPasswordCommand=<user-specified command>
For example:
# Linux / Docker (secret-tool, systemd-creds, Docker secrets, pass, ...)IbPasswordCommand=cat /run/secrets/ib_password
# Windows (Credential Manager via the PowerShell CredentialManager module)IbPasswordCommand=powershell -NoProfile -c "(Get-StoredCredential -Target IBC).GetNetworkCredential().Password"# macOS (Keychain)IbPasswordCommand=security find-generic-password -a myuser -s IBC-IBKR -w
At the moment IBC needs the credentials, it runs the command, takes its stdout (trailing newline stripped) as the password, and holds it only in memory. Nothing else changes — and IBC gains no platform-specific code or dependencies; each OS's secret store is reached by whatever tool the user already has.
The problem it solves
Today the password can reach IBC by two routes, and both leave it observable:
config.ini — plain text at rest. The userguide already recommends filesystem/OS measures (as discussed in Securing cleartext user-id/pwd #129), but the value is still readable by anything running as the user.
Start-script variables — the value travels via the java command line and is visible to any process via ps for the gateway's entire lifetime. This was noted in Allow user to use env variables with gatewaystart.sh #57 back in 2019 ("visible to anyone via ps") and raised again recently in Securing cleartext user-id/pwd #129 with a pointer to the relevant ibcstart.sh lines. I've verified it on a current install: the password appears verbatim in the java argv from launch until shutdown.
The key point — and the reason I think this belongs in IBC's Java rather than in the user-editable script region: no user-side change can fix this. Anything a user does in the scripts must ultimately hand the secret to the JVM via argv or the environment, both observable. Only code inside IBC can fetch a secret without exposing it. (I'm aware of the IbcLoader sample, which allows overriding LoginManager.IBAPIPassword() — that is a viable programmatic route for Java-comfortable users, but a config-level command would make the same hygiene available to everyone.)
Proposed semantics (to preempt ambiguity — all open to discussion)
New optional settings IbPasswordCommand and FIXPasswordCommand (and possibly IbLoginIdCommand/FIXLoginIdCommand for symmetry, though the user id is less sensitive).
Executed via /bin/sh -c on unix, cmd /c on Windows, at the moment IBC needs the credential (not at startup).
stdout with one trailing newline stripped = the password; stderr passed through to the IBC log.
Non-zero exit, empty output, or a timeout (say 15s) ⇒ behave exactly as if the corresponding password setting were unset — i.e. the login dialog prompts — plus a log line that never echoes any output.
If both IbPassword and IbPasswordCommand are set: the command wins, with a warning (mirrors the existing "command line overrides ini" precedence style).
Because the setting lives in each instance's config.ini, separate live/paper instances naturally carry their own commands — no shared global state.
What this enables, per platform
Platform
Example command
Store
Linux (headless)
systemd-creds decrypt ... or cat /run/secrets/ib_password
systemd-creds / Docker secrets
Linux (desktop)
secret-tool lookup service ibc
GNOME Keyring / KWallet
Windows
a one-line PowerShell CredentialManager / DPAPI read
Credential Manager
macOS
security find-generic-password -a user -s IBC-IBKR -w
Keychain
The Docker row may be of particular interest given #67 and #88 — cat /run/secrets/... is the standard Docker-secrets pattern and would remove any need to bake credentials into images or ini files.
Precedents
This is a long-established pattern rather than an invention: restic (RESTIC_PASSWORD_COMMAND), msmtp (passwordeval), mutt, borg, and git's credential helpers all delegate secret retrieval to a user command precisely to stay store-agnostic and dependency-free.
What this is not
It is not encryption and I wouldn't present it as such — the secret still transits a pipe and lives briefly in JVM memory, and it complements rather than replaces second-factor authentication. I understand the project's history of removing the old password-scrambling feature on exactly the grounds that obfuscation shouldn't masquerade as security; this proposal is in that same spirit: it changes where the secret rests and what can observe it (no file, no argv, no env), and claims nothing more.
Offer
If the approach is welcome, I'd be happy to submit a PR — the implementation looks small (execute-and-read at the existing password-retrieval seam), dependency-free, plus documentation for userguide.md and the resources/config.ini template. Equally happy to adjust the semantics above to your preferences first.
Disclosure: this proposal was researched and drafted with AI assistance (Claude). The technical claims were verified against a real installation — the argv exposure was measured on a live gateway process, and the script/ini behaviour was read from the shipped IBC 3.23 scripts and the current master sources — and I've reviewed the text and stand behind it.
Summary
I'd like to propose a small, dependency-free enhancement: a config setting that lets IBC obtain the password by running a user-specified command at login time, instead of reading a literal value. One mechanism, platform-neutral in IBC itself — the command supplies the platform specifics:
IbPasswordCommand=<user-specified command>For example:
At the moment IBC needs the credentials, it runs the command, takes its stdout (trailing newline stripped) as the password, and holds it only in memory. Nothing else changes — and IBC gains no platform-specific code or dependencies; each OS's secret store is reached by whatever tool the user already has.
The problem it solves
Today the password can reach IBC by two routes, and both leave it observable:
config.ini— plain text at rest. The userguide already recommends filesystem/OS measures (as discussed in Securing cleartext user-id/pwd #129), but the value is still readable by anything running as the user.psfor the gateway's entire lifetime. This was noted in Allow user to use env variables with gatewaystart.sh #57 back in 2019 ("visible to anyone viaps") and raised again recently in Securing cleartext user-id/pwd #129 with a pointer to the relevantibcstart.shlines. I've verified it on a current install: the password appears verbatim in the java argv from launch until shutdown.The key point — and the reason I think this belongs in IBC's Java rather than in the user-editable script region: no user-side change can fix this. Anything a user does in the scripts must ultimately hand the secret to the JVM via argv or the environment, both observable. Only code inside IBC can fetch a secret without exposing it. (I'm aware of the
IbcLoadersample, which allows overridingLoginManager.IBAPIPassword()— that is a viable programmatic route for Java-comfortable users, but a config-level command would make the same hygiene available to everyone.)Proposed semantics (to preempt ambiguity — all open to discussion)
IbPasswordCommandandFIXPasswordCommand(and possiblyIbLoginIdCommand/FIXLoginIdCommandfor symmetry, though the user id is less sensitive)./bin/sh -con unix,cmd /con Windows, at the moment IBC needs the credential (not at startup).IbPasswordandIbPasswordCommandare set: the command wins, with a warning (mirrors the existing "command line overrides ini" precedence style).Because the setting lives in each instance's
config.ini, separate live/paper instances naturally carry their own commands — no shared global state.What this enables, per platform
systemd-creds decrypt ...orcat /run/secrets/ib_passwordsecret-tool lookup service ibcCredentialManager/ DPAPI readsecurity find-generic-password -a user -s IBC-IBKR -wThe Docker row may be of particular interest given #67 and #88 —
cat /run/secrets/...is the standard Docker-secrets pattern and would remove any need to bake credentials into images or ini files.Precedents
This is a long-established pattern rather than an invention:
restic(RESTIC_PASSWORD_COMMAND),msmtp(passwordeval),mutt,borg, and git's credential helpers all delegate secret retrieval to a user command precisely to stay store-agnostic and dependency-free.What this is not
It is not encryption and I wouldn't present it as such — the secret still transits a pipe and lives briefly in JVM memory, and it complements rather than replaces second-factor authentication. I understand the project's history of removing the old password-scrambling feature on exactly the grounds that obfuscation shouldn't masquerade as security; this proposal is in that same spirit: it changes where the secret rests and what can observe it (no file, no argv, no env), and claims nothing more.
Offer
If the approach is welcome, I'd be happy to submit a PR — the implementation looks small (execute-and-read at the existing password-retrieval seam), dependency-free, plus documentation for
userguide.mdand theresources/config.initemplate. Equally happy to adjust the semantics above to your preferences first.Related: #129, #57, #88, #339.
Disclosure: this proposal was researched and drafted with AI assistance (Claude). The technical claims were verified against a real installation — the argv exposure was measured on a live gateway process, and the script/ini behaviour was read from the shipped IBC 3.23 scripts and the current master sources — and I've reviewed the text and stand behind it.