Welcome to Chapter 4! In the previous chapter, Tool Availability Check, we learned how to find the GitHub CLI tool (gh) on the user's computer.
Now that we have found the tool, we need to run it. But we must be careful. We are about to handle the user's authentication tokenβa secret password. In this chapter, we will learn how to verify this password without ever looking at it, ensuring it never leaks into our logs.
Imagine you are a security guard at a bank vault. A person approaches and says they know the combination.
You have two ways to verify this:
The Use Case:
We want to verify if the user is logged into GitHub. The command to do this is gh auth token.
We need the Silent Way. We want the computer to run the command but ignore the text and only look for the "Green Light" (Success) or "Red Light" (Failure).
To understand secure execution, we need to separate two things a computer program produces:
stdout): The text the program "speaks." (e.g., ghp_SecretToken123). This is dangerous for us.0: Success (The green light).1 (or higher): Failure (The red light).Our Strategy: We will gag the "mouth" of the program so it can't speak the token, but we will watch the "exit code" to see if it worked.
We use a library called execa to run commands. It allows us to configure exactly what happens to the output.
Here is the basic pattern for running a command securely:
import { execa } from 'execa'
async function checkLogin() {
// Run the command, but ignore the text output
const result = await execa('gh', ['auth', 'token'], {
stdout: 'ignore', // <--- THE SECURITY FEATURE
reject: false // Don't crash on failure
})
// Only check the exit code
if (result.exitCode === 0) {
console.log("Verified!")
}
}
gh auth token.result.stdout will be undefined or empty. The actual token never enters our application's memory variable.true (it worked) or false (it didn't).Let's visualize the difference between a standard execution and our secure execution.
In a normal execution, data flows from the System to the App. In our secure execution, we cut that wire.
Let's look at the actual code we wrote in ghAuthStatus.ts (first introduced in Telemetry Data Source). We will break down the options object line-by-line.
// ghAuthStatus.ts
// ... imports ...
export async function getGhAuthStatus() {
// ... previous checks ...
// Securely run the command
const { exitCode } = await execa('gh', ['auth', 'token'], {
stdout: 'ignore', // 1. Security: Don't read the token
stderr: 'ignore', // 2. Cleanliness: Don't read errors
timeout: 5000, // 3. Safety: Stop after 5 seconds
reject: false, // 4. Control: Don't throw an exception
})
return exitCode === 0 ? 'authenticated' : 'not_authenticated'
}
Explanation of Options:
stdout: 'ignore': This is the most important line. It tells Node.js to detach the output stream. The subprocess writes the token to "nowhere." Even if we wanted to log it, we couldn't.stderr: 'ignore': If the command fails (e.g., "Token not found"), it usually prints an error message. We ignore this too because we don't need the details, we just need the status.timeout: 5000: If the gh tool freezes, we don't want our app to hang forever. We kill the process after 5 seconds.reject: false: Normally, execa throws a scary error (exception) if the command fails. We set this to false because "not being logged in" isn't a program crash for us; it's just a valid state we want to handle gracefully.In this chapter, we mastered Secure Subprocess Execution.
We learned:
execa options to create a safe, crash-resistant check.We have now verified the tool exists (Tool Availability Check) and verified the user is logged in safely.
However, there is one final detail. Why did we use gh auth token specifically, instead of gh auth status? It turns out, where the verification happens (Local vs. Network) matters a lot for speed and reliability.
Let's explore this in the final chapter.
Next Chapter: Local-Only Verification
Generated by Code IQ