7 मिनट पढ़ें

क्या forced SSH commands में AI service account को सुरक्षित रखा जा सकता है?

Forced SSH commands AI-controlled service accounts को नामित server actions तक सीमित रखते हैं, जबकि human approval credential boundary पर बनी रहती है।

क्या forced SSH commands में AI service account को सुरक्षित रखा जा सकता है?

AI agent को कभी ऐसा SSH credential नहीं मिलना चाहिए जिसका अर्थ हो, «account जो कुछ कर सकता है, वह सब कर लो।» यह permission boundary नहीं है। यह उसे खोजने का निमंत्रण है, अक्सर ऐसे argument के ज़रिए जिसकी आपको उम्मीद नहीं थी, उस forwarded connection के ज़रिए जिसे बंद करना आप भूल गए, या उस deployment script के ज़रिए जो caller पर ज़रूरत से ज़्यादा भरोसा करती है।

Forced SSH commands authentication के बाद शुरू होने वाली प्रक्रिया पर remote server को अंतिम नियंत्रण देते हैं। Deployment और diagnostic accounts के लिए ये अच्छे विकल्प हैं, क्योंकि ये एक अस्पष्ट क्षमता, remote shell access, की जगह आपके नियंत्रण और निरीक्षण में रहने वाला एक नामित operation देते हैं। ये credential के उपयोग के लिए human approval की जगह नहीं लेते। इन दोनों controls को अलग रखें: व्यक्ति तय करता है कि agent credential इस्तेमाल कर सकता है या नहीं, और server तय करता है कि वह credential कौन-सा सीमित action कर सकता है।

Forced command execution को सीमित करता है, authentication को नहीं

Forced command sshd को निर्देश देता है कि client shell माँगे या कोई दूसरा command भेजे, फिर भी server द्वारा चुना गया program चलाया जाए। Client पहले भी authentication करता है। यह अंतर तब तक साफ़ लगता है जब तक service account किसी agent configuration में दिखाई नहीं देता और लोग सफल login को approved deployment समझना शुरू नहीं कर देते।

OpenSSH इस control को दो जगह support करता है। आप authorized_keys में किसी public key के साथ command="/path/to/wrapper" जोड़ सकते हैं, या sshd_config में किसी user या group के लिए ForceCommand सेट कर सकते हैं। दोनों मामलों में sshd client द्वारा माँगा गया command SSH_ORIGINAL_COMMAND environment variable में दर्ज करता है और उसकी जगह forced program शुरू करता है।

OpenSSH का sshd(8) manual पहले हिस्से पर बिल्कुल स्पष्ट है: command option authentication के बाद बताए गए command को चलाने के लिए मजबूर करता है। वह यह भी बताता है कि मूल command forced program के लिए उपलब्ध रहता है। यही दूसरा विवरण कई कमजोर designs की वजह बनता है। Wrapper को untrusted client से एक string मिलती है। उसे इस string को request की तरह parse करना चाहिए, shell में नहीं भेजना चाहिए।

जब एक account के पास कई सावधानी से अलग किए गए credentials हों, तब per-key form इस्तेमाल करें। Release credential deployment wrapper शुरू कर सकता है, जबकि operations credential read-only diagnostic wrapper शुरू कर सकता है। इससे authorized_keys में intent साफ़ दिखता है और आप account की दूसरी access बदले बिना एक credential हटा सकते हैं।

जब account को authentication के तरीके की परवाह किए बिना कभी general shell नहीं देना हो, तब ForceCommand इस्तेमाल करें। इसमें वह password भी शामिल है जिसे बंद करना आप भूल गए हों, future certificate authority, या वह administrator जो ज़रूरी options कॉपी किए बिना एक और public key जोड़ देता है। Match User deploy block review के दौरान इस नियम को नज़रअंदाज़ करना कठिन बनाता है।

इन दोनों forms का इस्तेमाल human administrator account को automation account में बदलने के लिए न करें। लोगों को repair work के लिए कभी-कभी वास्तविक shell चाहिए होती है। Automation के लिए अलग Unix account, अलग credential, अलग command wrapper और काम के अनुरूप ownership boundaries दें।

Deployment entry point का नियंत्रण server के पास होना चाहिए

Deployment account को generic command interpreter में नहीं, बल्कि आपके नियंत्रण वाली एक script में प्रवेश करना चाहिए। Script छोटी request vocabulary स्वीकार कर सकती है, लेकिन repository path, target directory, service unit और executable का चुनाव उसे स्वयं करना चाहिए।

यह authorized_keys entry एक credential को wrapper तक सीमित करती है और उन connection features को अस्वीकार करती है जिनकी deployment account में कोई जगह नहीं है:

restrict,command="/usr/local/libexec/release-gate" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... release-agent

restrict उपयोगी है क्योंकि OpenSSH के documentation के अनुसार यह port forwarding, agent forwarding, X11 forwarding और pseudo-terminal allocation को बंद करने का संक्षिप्त तरीका है। इसका सटीक व्यवहार आपके server द्वारा support किए जाने वाले OpenSSH options पर निर्भर करता है, इसलिए इसे अपने version पर test करें। अगर आपके environment में review या compatibility के लिए explicit options चाहिए, तो उन्हें साफ़-साफ़ लिखें:

command="/usr/local/libexec/release-gate",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... release-agent

Wrapper को free-form deployment command नहीं लेना चाहिए। Callers को fixed verbs और सीमित value दें। उदाहरण के लिए, caller केवल immutable revision के आधार पर release माँग सकता है:

ssh [email protected] "release 9f2a7c6d1e4b8a03"

एक सुरक्षित wrapper उस grammar को और कुछ नहीं स्वीकार कर सकता है:

#!/bin/sh
set -eu

request=${SSH_ORIGINAL_COMMAND-}
case "$request" in
  "release "[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]* )
    revision=${request#release }
    case "$revision" in
      *" "*|*[!0-9a-f]*)
        echo "invalid revision" >&2
        exit 64
        ;;
    esac
    exec /usr/local/libexec/run-release "$revision"
    ;;
  *)
    echo "unsupported remote request" >&2
    exit 64
    ;;
esac

अगर आपके revision format में निश्चित लंबाई चाहिए, तो इस example में length check भी जोड़ना होगा। Production wrapper को पूरा immutable object ID या आपके द्वारा तय format वाला release identifier स्वीकार करना चाहिए। main जैसे branch name को स्वीकार न करें, अगर approval और deployment के बीच caller उसे बदल सकता है। Branch एक pointer है। Immutable revision से approval record, deployment log और बनने वाला artifact एक ही चीज़ का reference दे सकते हैं।

run-release script को absolute paths का इस्तेमाल करना चाहिए और अपना environment खुद सेट करना चाहिए। Caller द्वारा दिए गए PATH, working directory, locale, GIT_DIR, GIT_SSH_COMMAND या LD_PRELOAD पर भरोसा न करें। शुरुआत का एक न्यूनतम रूप ऐसा हो सकता है:

#!/bin/sh
set -eu
PATH=/usr/sbin:/usr/bin:/sbin:/bin
export PATH
unset CDPATH ENV BASH_ENV GIT_DIR GIT_WORK_TREE GIT_SSH_COMMAND
cd /srv/release-repo

revision=$1
/usr/bin/git cat-file -e "$revision^{commit}"
/usr/local/libexec/build-and-activate "$revision"

Account को केवल उन्हीं files का owner होना चाहिए जिन्हें उसे बदलना ज़रूरी है। अगर account को service restart करनी है, तो passwordless access से किसी general package manager या shell तक पहुँच देने के बजाय fixed arguments वाला एक संकीर्ण sudoers command दें। जो deployment account अपना wrapper लिख सकता है, अपना authorized_keys बदल सकता है या अपने code को चलाने वाली unit edit कर सकता है, वह अक्सर व्यापक control हासिल कर सकता है। केवल SSH configuration नहीं, इन paths की भी जाँच करें।

SSH_ORIGINAL_COMMAND input है, command line नहीं

Forced-command में सबसे आम गलती यह line है:

sh -c "$SSH_ORIGINAL_COMMAND"

यह आपके बनाए control को निष्प्रभावी कर देती है। Client release goodrev; curl ... | sh, command substitution, redirected output या सावधानी से quote किए गए ऐसे argument का अनुरोध कर सकता है जो privileged tool तक पहुँच जाए। जो wrapper eval, sh -c, bash -c या unquoted expansion चलाता है, वह अलग filename के तहत remote shell access फिर से बना देता है।

Full shell parser बनाने की कोशिश न करें। उसकी ज़रूरत नहीं है। जानबूझकर छोटा protocol तय करें और उससे बाहर की हर चीज़ अस्वीकार करें। Deployment account के लिए request एक verb और एक identifier हो सकती है। Diagnostic account के लिए request health या version जैसे एक exact word तक सीमित हो सकती है।

Diagnostics के लिए dispatch wrapper parsing से पूरी तरह बच सकता है:

#!/bin/sh
set -eu

case "${SSH_ORIGINAL_COMMAND-}" in
  health)
    exec /usr/local/libexec/report-health
    ;;
  queue-depth)
    exec /usr/local/libexec/report-queue-depth
    ;;
  version)
    exec /usr/local/libexec/report-version
    ;;
  "")
    echo "a diagnostic name is required" >&2
    exit 64
    ;;
  *)
    echo "diagnostic is not allowed" >&2
    exit 64
    ;;
esac

इन diagnostic scripts को भी अपने arguments पर नियंत्रण रखना चाहिए। report-health को fixed binaries को fixed local sockets या ज्ञात service names पर चलाना चाहिए। उसे host parameter लेकर curl "$host" नहीं चलाना चाहिए और न ही journal filter लेकर उसे shell में भेजना चाहिए। Read-only command भी database credentials, internal topology, environment values या customer data उजागर कर सकता है।

लोग अक्सर कहते हैं कि carefully quoted shell command पर्याप्त है क्योंकि calling agent trusted है। यह दावा तब टूट जाता है जब agent hostile repository instructions का पालन करता है, value को instruction समझ लेता है या साधारण गलती करता है। Remote server यह नहीं जान सकता कि खतरनाक request दुर्भावना से आई है या किसी अति-उत्साही tool call से। उसे केवल input दिखाई देता है। उसका निर्णय deterministic बनाएँ।

अगर structured inputs चाहिए, तो bounded format भेजें और ऐसे parser से parse करें जो extra fields अस्वीकार कर दे। JSON अपने आप सुरक्षित नहीं होता, क्योंकि shell wrapper उसे फिर भी गलत तरीके से संभाल सकता है। release <64 lowercase hex characters> जैसी छोटी request को validate, document, test और audit करना optional fields वाले JSON blob की तुलना में आसान है।

Forwarding restriction की भावना को दरकिनार कर सकता है

Forced command अपने आप authenticated client को SSH को tunnel की तरह इस्तेमाल करने से नहीं रोकता। OpenSSH manual command execution और forwarding को अलग controls मानता है। अगर आप केवल command="..." जोड़ते हैं, तो server configuration के बाकी हिस्सों के आधार पर client sshd से local port को internal service तक forward करने का अनुरोध कर सकता है।

यह इसलिए महत्वपूर्ण है क्योंकि restricted account के पास ऐसा network access हो सकता है जो agent के पास नहीं है। Agent remote host पर /usr/bin/ps नहीं चला सकता, फिर भी forwarding खुली रहने पर उस host के ज़रिए database port तक पहुँच सकता है। ऐसे में account deployment identity नहीं रह जाता, बल्कि network pivot बन जाता है।

जिस account को interactive session की ज़रूरत नहीं है, उसके लिए इन सभी को बंद करें, जब तक आप यह स्पष्ट न कर सकें कि account को इनमें से किसी की ज़रूरत क्यों है:

  • TCP forwarding
  • agent forwarding
  • X11 forwarding
  • pseudo-terminal allocation
  • user-controlled environment variables

आधुनिक OpenSSH deployments में restrict पहली चार categories संभालता है। अगर account को सचमुच किसी एक exception की ज़रूरत है, तो restriction set को पूरी तरह हटाने के बजाय उसे सीमित करें। OpenSSH permitopen="host:port" जैसे options support करता है, जिनसे destination forwarding सीमित की जा सकती है। इसे अलग access design मानें और allowed तथा denied दोनों destinations को test करें।

Wrapper के outbound network access की भी जाँच करें। ऐसा deployment script जो arbitrary URLs fetch कर सकती है, arbitrary repositories clone कर सकती है या arbitrary data बाहर भेज सकती है, SSH forwarding बंद होने पर भी एक व्यापक channel रखती है। Fixed artifact sources और pinned revisions यह exposure घटाते हैं। बाकी नियंत्रण के लिए firewall rules या service-specific credentials की ज़रूरत पड़ सकती है।

Connection खुलने से पहले approval होनी चाहिए

Forced commands से पहले मंज़ूरी रखें
Sallyport सर्वर के forced command के यह तय करने से पहले credential उपयोग को मंज़ूरी देता है कि क्या चल सकता है।

Forced command approved SSH उपयोग से होने वाले नुकसान को सीमित करता है। यह तय नहीं करता कि मौजूदा agent process को credential का इस्तेमाल करना चाहिए या नहीं। यह निर्णय credential boundary पर, agent के SSH connection बनाने से पहले होना चाहिए।

Autonomous coding agents के लिए यह खास तौर पर महत्वपूर्ण है। Repository agent को deployment command चलाने का निर्देश दे सकती है। Tool output भी ऐसा अनुरोध कर सकता है। Compromised dependency agent को उसी दिशा में मोड़ सकती है। अगर credential agent के environment या filesystem में रखा है, तो agent उस क्षण किसी व्यक्ति को दिखाए बिना उसका इस्तेमाल कर सकता है।

SSH private keys को agent process से बाहर रखें और जब कोई नया agent run पहली बार access माँगे, तब approval लें। High-consequence accounts के लिए हर credential उपयोग पर approval लें। इसके बाद remote forced command उस action पर एक hard ceiling लगा देता है जिसे approval अधिकृत करती है।

Sallyport इस विभाजन को इस तरह लागू करता है कि SSH keys उसके encrypted vault में रहती हैं, नए agent processes को default रूप से प्रति-session authorize किया जाता है, और key agent को देने के बजाय SSH को उसके sp-ssh helper के ज़रिए चलाया जाता है।

Approval card को server authorization न समझें। Approval का सवाल है, «क्या यह process अभी इस credential का इस्तेमाल कर सकता है?» Server का सवाल है, «Login के बाद यह credential क्या कर सकता है?» दोनों सवालों के जवाब ज़रूरी हैं क्योंकि दोनों अलग तरह से विफल होते हैं। Approval किसी चौंकाने वाले process को रोक सकती है। Forced commands किसी approved process को release credential को shell में बदलने से रोक सकते हैं।

Approval description उपयोगी बनाएँ। Credential label में environment और action का नाम लिखें, जैसे production release या staging diagnosticsdeploy-key-2 जैसा label reviewer से interruption के दौरान पुरानी जानकारी याद रखने की अपेक्षा करता है। इसी तरह routine approvals automatic clicks में बदल जाती हैं।

Allowlist बढ़ने से पहले deployment और diagnosis अलग करें

अनुरोध करने वाले प्रोसेस को मंज़ूरी दें
नया एजेंट प्रोसेस अपनी पहली SSH कॉल से पहले अपनी code-signing authority दिखाता है।

Deployment और diagnosis दोनों को SSH की ज़रूरत पड़ सकती है, इसलिए वे समान लगते हैं। लेकिन उनके data flows और failure modes अलग होते हैं। जहाँ संभव हो, उन्हें अलग accounts या अलग forced-command credentials के पीछे रखें।

Deployment account state बदलता है। वह fixed revision fetch कर सकता है, artifact build कर सकता है, release directory बदल सकता है और एक service restart कर सकता है। उसका output revision, target, exit status और छोटा failure message बताए। उसे arbitrary log access, process inspection या database queries की ज़रूरत नहीं है।

Diagnostic account state पढ़ता है। वह health endpoint का result, सीमित queue count, service version या सावधानी से filtered local log का tail दिखा सकता है। उसे services restart नहीं करनी चाहिए, files rotate नहीं करनी चाहिए, हर process query नहीं करना चाहिए और arbitrary paths पढ़ने नहीं चाहिए। जैसे ही diagnostic wrapper user-provided file name, unit name, host या command option स्वीकार करे, उसके input model की फिर से समीक्षा करें।

एक combined account अक्सर ऐसी निर्दोष सूची से शुरू होता है:

release <revision>
health
logs <service>
restart <service>

फिर किसी को logs api --since चाहिए, किसी और को emergency restart, और wrapper journalctl या systemctl को arguments आगे भेजना शुरू कर देता है। जल्द ही code में ऐसे special cases भर जाते हैं जिन्हें कोई समझा नहीं सकता। ऐसा होने से पहले accounts अलग कर दें। अलग credentials से आप production changes के लिए अधिक सख्त approval माँग सकते हैं और कम जोखिम वाला diagnostic workflow अलग रख सकते हैं।

हर action को ऐसा record बनाना चाहिए जिसमें यह लिखा हो कि wrapper ने क्या स्वीकार किया, केवल opaque SSH command string नहीं। Release के लिए immutable revision और target name log करें। Diagnosis के लिए named diagnostic और उसका परिणाम log करें। Command arguments और logs दोनों में secret values न रखें। अगर किसी action को secret चाहिए, तो remote script उसे अपने controlled mechanism से प्राप्त करे, SSH client से स्वीकार न करे।

Disposable client से denial paths test करें

Restricted account वास्तव में तभी restricted है जब आप उन requests को test कर लें जिन्हें उसे अस्वीकार करना है। Production environment में configuration पर भरोसा करने से पहले disposable account या test host से ये जाँचें चलाएँ। Examples मानते हैं कि credential server पर पहले से installed है।

ssh [email protected] "release 9f2a7c6d1e4b8a03"
ssh [email protected]
ssh [email protected] "id"
ssh [email protected] "release 9f2a; id"
ssh -N -L 15432:db.internal:5432 [email protected]
ssh -tt [email protected] "health"

पहला command तभी release wrapper तक पहुँचना चाहिए जब revision उसके नियमों पर खरी उतरे। अगले तीन commands wrapper का denial message और nonzero exit status देकर विफल होने चाहिए। Port-forwarding प्रयास listener स्थापित करने से पहले विफल होना चाहिए। Terminal request विफल होनी चाहिए या बिना terminal के चलनी चाहिए, यह इस बात पर निर्भर करेगा कि आपका client denied allocation को कैसे report करता है।

इसके बाद कम स्पष्ट cases test करें। Leading और trailing spaces, tabs, empty quoted command, newline characters, बहुत लंबा argument, Unicode whitespace, command substitutions, redirections और duplicate arguments आज़माएँ। अगर आपका shell या wrapper इनमें से किसी को normalize करके accepted request बना देता है, तो grammar को और सख्त करें।

Test के हिस्से के रूप में account की file permissions और ownership भी जाँचें। जो attacker /usr/local/libexec/release-gate बदल सकता है, उसे SSH bypass करने की ज़रूरत नहीं है। जो account अपने deployment source को बदल सकता है, वह अधिक privilege के साथ चलने वाले code को भी बदल सकता है। पूरी chain देखें: authorized_keys, sshd configuration, wrapper, deployment scripts, service definitions, writable directories और कोई भी sudoers entry।

Boundary के दोनों तरफ request का audit करें

संकीर्ण accounts को मंज़ूरी के साथ जोड़ें
Forced commands सर्वर account की सीमा तय करते हैं, जबकि Sallyport नियंत्रित करता है कि एजेंट कब उसकी SSH key का अनुरोध कर सकता है।

Remote logs बताते हैं कि server ने क्या स्वीकार किया। Credential-boundary logs बताते हैं कि किस local process ने connect करने की क्षमता माँगी। दोनों रखें क्योंकि कोई भी log दूसरे का सवाल नहीं बता सकता।

Remote side पर authentication success, forced wrapper का accepted operation, immutable revision या diagnostic name, request identifier और final status log करें। इन records को ऐसी जगह भेजें जिसे service account बदल न सके। Raw SSH_ORIGINAL_COMMAND log न करें, अगर callers उसमें secret material डाल सकते हैं। बेहतर है कि आपका protocol secret material स्वीकार ही न करे।

Local side पर session identity और individual SSH action request सुरक्षित रखें। Sallyport agent runs और individual calls को एक encrypted, hash-chained audit log से अलग journals में record करता है, और sp audit verify vault key के बिना offline उस chain को verify कर सकता है।

Hash chain खराब permission को अच्छी permission में नहीं बदलती। लेकिन इससे recorded history में बाद के बदलावों का पता लगाना आसान हो जाता है। Failed deployment, disputed approval या चौंकाने वाले command request के बाद यह उपयोगी है। यह एक अच्छी discipline भी बनाती है: action vocabulary पहले से तय करें, ताकि records इंसान समझ सकें।

पहला implementation उबाऊ होना चाहिए। Dedicated Unix account बनाएँ, एक forced wrapper रखें, fixed input grammar वाला एक operation रखें, forwarding बंद करें और ऐसा test लिखें जो साबित करे कि ssh account@host shell नहीं देता। Capabilities तभी जोड़ें जब आप उनके input, output, file access, network access और approval देने वाले व्यक्ति का नाम बता सकें।

सामान्य प्रश्न

Forced SSH command क्या होता है?

authorized_keys में command="..." विकल्प वाला SSH account इस्तेमाल करें, या जब उस account के लिए हर authentication method को एक ही नियम का पालन करना हो, तो sshd_config में ForceCommand इस्तेमाल करें। सर्वर client द्वारा भेजे गए command की जगह आपका wrapper चलाता है और मूल अनुरोध को SSH_ORIGINAL_COMMAND के ज़रिए पास करता है।

क्या forced SSH commands AI service account को सुरक्षित करने के लिए पर्याप्त हैं?

नहीं। Forced command सफल authentication के बाद SSH server द्वारा शुरू किए जाने वाले program को सीमित करता है, लेकिन यह तय नहीं करता कि credential का इस्तेमाल कौन कर सकता है। इसे ऐसे credential boundary के साथ इस्तेमाल करें जिसमें नए agent run या संवेदनशील उपयोग के लिए व्यक्ति की मंज़ूरी ज़रूरी हो। इसके बाद server account को इतना सीमित रखें कि उस मंज़ूरी का प्रभाव भी नियंत्रित रहे।

मुझे ForceCommand इस्तेमाल करना चाहिए या authorized_keys command?

आमतौर पर authorized_keys में अलग key बेहतर रहती है। इससे एक credential और एक forced-command rule के बीच साफ़ संबंध बना रहता है, जबकि shared account setting लोगों और automation दोनों को प्रभावित कर सकती है। ForceCommand तब इस्तेमाल करें जब आप जानबूझकर चाहते हों कि restricted account तक पहुँचने वाला हर रास्ता उसी wrapper तक जाए।

Forced command को मूल SSH command कैसे मिलता है?

जब OpenSSH forced command चलाता है, तो client द्वारा माँगा गया command SSH_ORIGINAL_COMMAND में रखता है। इस मान को अविश्वसनीय input मानें: shell metacharacters और ऐसे options अस्वीकार करें जिन्हें आपने डिज़ाइन नहीं किया है, और केवल कुछ छोटे, स्पष्ट command forms से मिलान करें।

क्या authorized_keys में command= SSH port forwarding बंद करता है?

नहीं। केवल command="..." विकल्प port forwarding, agent forwarding, X11 forwarding या pseudo-terminal को बंद नहीं करता। जहाँ उपयुक्त हो वहाँ restrict जोड़ें, या हर capability को स्पष्ट रूप से बंद करके client से परिणाम की जाँच करें।

मैं SSH account को केवल deployments तक कैसे सीमित करूँ?

Deployment account को fixed paths, fixed working directory, सीमित environment और deployment targets की allowlist वाली आपकी अपनी एक script चलानी चाहिए। किसी arbitrary branch, host, path या shell fragment को स्वीकार करके उसे git, rsync, sudo या shell तक आगे न भेजें।

Forced command wrapper को क्या अस्वीकार करना चाहिए?

Empty request, shell, अज्ञात subcommand, गलत arguments या अनपेक्षित whitespace अथवा metacharacters वाले request पर nonzero status लौटाएँ। Rejection को authenticated account और source information के साथ log करें, लेकिन environment variables या command text के ज़रिए भेजे गए secrets को कभी log न करें।

क्या AI coding agents forced SSH commands का noninteractively इस्तेमाल कर सकते हैं?

Forced commands SSH के साथ काम करते हैं क्योंकि authentication के बाद कौन-सा program शुरू होगा, यह AI process नहीं बल्कि server तय करता है। Remote host पर interactive prompt की ज़रूरत नहीं होती, इसलिए credential boundary पर approval बनाए रखते हुए इन्हें noninteractive agent runs के लिए इस्तेमाल किया जा सकता है।

मैं forced SSH account के actions का audit कैसे करूँ?

Remote wrapper logs, deployment logs और SSH authentication logs सुरक्षित रखें, फिर उन्हें credential-use record के साथ मिलाएँ। Tamper-evident local action journal उपयोगी है क्योंकि यह दर्ज करता है कि remote server को connection मिलने से पहले किस agent process ने credential इस्तेमाल करने का अनुरोध किया था।

क्या deployment और diagnostic SSH access के लिए अलग accounts इस्तेमाल करने चाहिए?

जब diagnostic task का उद्देश्य, allowed commands या deployment से होने वाला प्रभाव अलग हो, तो अलग account इस्तेमाल करें। दोनों को एक wrapper में मिलाने पर allowlist अक्सर बढ़ती जाती है और वह अनजाने में remote shell बन सकती है।

Sallyport

Sallyport आपके AI एजेंट के लिए API कॉल और SSH कमांड चलाता है। कुंजियाँ आपके Mac पर एक लोकल वॉल्ट में रहती हैं; आप हर रन को स्वीकृत करते हैं और हर क्रिया एक सीलबंद जर्नल में दर्ज होती है।

© 2026 Sallyport · Apache-2.0 के तहत ओपन सोर्स · Oleg Sotnikov