Skip to content

Commit 53187a6

Browse files
authored
feat: add support for ignoring HTTPS certificate errors (#93)
* feat: add support for ignoring HTTPS certificate errors * fix: update warning message for already running daemon to include ignore HTTPS errors option * docs: add documentation for --ignore-https-errors option in README and SKILL.md * feat: initialize ignore_https_errors flag in command context * fix: change launch_cmd to mutable for cdp value handling
1 parent 60534df commit 53187a6

12 files changed

Lines changed: 65 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ agent-browser snapshot -i -c -d 5 # Combine options
334334
| `--exact` | Exact text match |
335335
| `--headed` | Show browser window (not headless) |
336336
| `--cdp <port>` | Connect via Chrome DevTools Protocol |
337+
| `--ignore-https-errors` | Ignore HTTPS certificate errors (useful for self-signed certs) |
337338
| `--debug` | Debug output |
338339
339340
## Selectors

cli/src/commands.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,7 @@ mod tests {
12121212
args: None,
12131213
user_agent: None,
12141214
provider: None,
1215+
ignore_https_errors: false,
12151216
}
12161217
}
12171218

cli/src/connection.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ pub fn ensure_daemon(
194194
user_agent: Option<&str>,
195195
proxy: Option<&str>,
196196
proxy_bypass: Option<&str>,
197+
ignore_https_errors: bool,
197198
) -> Result<DaemonResult, String> {
198199
if is_daemon_running(session) && daemon_ready(session) {
199200
return Ok(DaemonResult {
@@ -266,6 +267,10 @@ pub fn ensure_daemon(
266267
cmd.env("AGENT_BROWSER_PROXY_BYPASS", pb);
267268
}
268269

270+
if ignore_https_errors {
271+
cmd.env("AGENT_BROWSER_IGNORE_HTTPS_ERRORS", "1");
272+
}
273+
269274
// Create new process group and session to fully detach
270275
unsafe {
271276
cmd.pre_exec(|| {
@@ -321,6 +326,10 @@ pub fn ensure_daemon(
321326
cmd.env("AGENT_BROWSER_PROXY_BYPASS", pb);
322327
}
323328

329+
if ignore_https_errors {
330+
cmd.env("AGENT_BROWSER_IGNORE_HTTPS_ERRORS", "1");
331+
}
332+
324333
// CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS
325334
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
326335
const DETACHED_PROCESS: u32 = 0x00000008;

cli/src/flags.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub struct Flags {
1616
pub args: Option<String>,
1717
pub user_agent: Option<String>,
1818
pub provider: Option<String>,
19+
pub ignore_https_errors: bool,
1920
}
2021

2122
pub fn parse_flags(args: &[String]) -> Flags {
@@ -40,6 +41,7 @@ pub fn parse_flags(args: &[String]) -> Flags {
4041
args: env::var("AGENT_BROWSER_ARGS").ok(),
4142
user_agent: env::var("AGENT_BROWSER_USER_AGENT").ok(),
4243
provider: env::var("AGENT_BROWSER_PROVIDER").ok(),
44+
ignore_https_errors: false,
4345
};
4446

4547
let mut i = 0;
@@ -115,6 +117,7 @@ pub fn parse_flags(args: &[String]) -> Flags {
115117
i += 1;
116118
}
117119
}
120+
"--ignore-https-errors" => flags.ignore_https_errors = true,
118121
_ => {}
119122
}
120123
i += 1;
@@ -127,7 +130,7 @@ pub fn clean_args(args: &[String]) -> Vec<String> {
127130
let mut skip_next = false;
128131

129132
// Global flags that should be stripped from command args
130-
const GLOBAL_FLAGS: &[&str] = &["--json", "--full", "--headed", "--debug"];
133+
const GLOBAL_FLAGS: &[&str] = &["--json", "--full", "--headed", "--debug", "--ignore-https-errors"];
131134
// Global flags that take a value (need to skip the next arg too)
132135
const GLOBAL_FLAGS_WITH_VALUE: &[&str] = &[
133136
"--session",

cli/src/main.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ fn main() {
200200
flags.user_agent.as_deref(),
201201
flags.proxy.as_deref(),
202202
flags.proxy_bypass.as_deref(),
203+
flags.ignore_https_errors,
203204
) {
204205
Ok(result) => result,
205206
Err(e) => {
@@ -223,6 +224,7 @@ fn main() {
223224
flags.user_agent.as_ref().map(|_| "--user-agent"),
224225
flags.proxy.as_ref().map(|_| "--proxy"),
225226
flags.proxy_bypass.as_ref().map(|_| "--proxy-bypass"),
227+
flags.ignore_https_errors.then(|| "--ignore-https-errors"),
226228
]
227229
.into_iter()
228230
.flatten()
@@ -235,6 +237,10 @@ fn main() {
235237
ignored_flags.join(", ")
236238
);
237239
}
240+
241+
if flags.ignore_https_errors {
242+
eprintln!("{} --ignore-https-errors ignored: daemon already running. Use 'agent-browser close' first to restart with this option.", color::warning_indicator());
243+
}
238244
}
239245

240246
// Validate mutually exclusive options
@@ -261,7 +267,7 @@ fn main() {
261267
// Connect via CDP if --cdp flag is set
262268
// Accepts either a port number (e.g., "9222") or a full URL (e.g., "ws://..." or "wss://...")
263269
if let Some(ref cdp_value) = flags.cdp {
264-
let launch_cmd = if cdp_value.starts_with("ws://")
270+
let mut launch_cmd = if cdp_value.starts_with("ws://")
265271
|| cdp_value.starts_with("wss://")
266272
|| cdp_value.starts_with("http://")
267273
|| cdp_value.starts_with("https://")
@@ -317,6 +323,10 @@ fn main() {
317323
})
318324
};
319325

326+
if flags.ignore_https_errors {
327+
launch_cmd["ignoreHTTPSErrors"] = json!(true);
328+
}
329+
320330
let err = match send_command(launch_cmd, &flags.session) {
321331
Ok(resp) if resp.success => None,
322332
Ok(resp) => Some(
@@ -401,6 +411,10 @@ fn main() {
401411
cmd_obj.insert("args".to_string(), json!(args_vec));
402412
}
403413

414+
if flags.ignore_https_errors {
415+
launch_cmd["ignoreHTTPSErrors"] = json!(true);
416+
}
417+
404418
if let Err(e) = send_command(launch_cmd, &flags.session) {
405419
if !flags.json {
406420
eprintln!("{} Could not configure browser: {}", color::warning_indicator(), e);

cli/src/output.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,7 @@ Options:
15351535
e.g., --proxy "http://user:pass@127.0.0.1:7890"
15361536
--proxy-bypass <hosts> Bypass proxy for these hosts (or AGENT_BROWSER_PROXY_BYPASS)
15371537
e.g., --proxy-bypass "localhost,*.internal.com"
1538+
--ignore-https-errors Ignore HTTPS certificate errors
15381539
-p, --provider <name> Cloud browser provider (or AGENT_BROWSER_PROVIDER env)
15391540
--json JSON output
15401541
--full, -f Full page screenshot

skills/agent-browser/SKILL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,10 @@ Usage:
347347
./templates/authenticated-session.sh https://app.example.com/login
348348
./templates/capture-workflow.sh https://example.com ./output
349349
```
350+
351+
## HTTPS Certificate Errors
352+
353+
For sites with self-signed or invalid certificates:
354+
```bash
355+
agent-browser open https://localhost:8443 --ignore-https-errors
356+
```

src/browser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ export class BrowserManager {
883883
extraHTTPHeaders: options.headers,
884884
userAgent: options.userAgent,
885885
...(options.proxy && { proxy: options.proxy }),
886+
ignoreHTTPSErrors: options.ignoreHTTPSErrors ?? false,
886887
}
887888
);
888889
this.isPersistentContext = true;
@@ -910,6 +911,7 @@ export class BrowserManager {
910911
extraHTTPHeaders: options.headers,
911912
userAgent: options.userAgent,
912913
...(options.proxy && { proxy: options.proxy }),
914+
ignoreHTTPSErrors: options.ignoreHTTPSErrors ?? false,
913915
});
914916
}
915917

src/daemon.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export async function startDaemon(options?: { streamPort?: number }): Promise<vo
248248
}
249249
: undefined;
250250

251+
const ignoreHTTPSErrors = process.env.AGENT_BROWSER_IGNORE_HTTPS_ERRORS === '1';
251252
await browser.launch({
252253
id: 'auto',
253254
action: 'launch' as const,
@@ -257,6 +258,7 @@ export async function startDaemon(options?: { streamPort?: number }): Promise<vo
257258
args,
258259
userAgent: process.env.AGENT_BROWSER_USER_AGENT,
259260
proxy,
261+
ignoreHTTPSErrors: ignoreHTTPSErrors,
260262
});
261263
}
262264

src/protocol.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,27 @@ describe('parseCommand', () => {
510510
const result = parseCommand(cmd({ id: '1', action: 'launch', cdpPort: 'invalid' }));
511511
expect(result.success).toBe(false);
512512
});
513+
514+
it('should parse launch with ignoreHTTPSErrors true', () => {
515+
const result = parseCommand(cmd({ id: '1', action: 'launch', ignoreHTTPSErrors: true }));
516+
expect(result.success).toBe(true);
517+
if (result.success) {
518+
expect(result.command.ignoreHTTPSErrors).toBe(true);
519+
}
520+
});
521+
522+
it('should parse launch with ignoreHTTPSErrors false', () => {
523+
const result = parseCommand(cmd({ id: '1', action: 'launch', ignoreHTTPSErrors: false }));
524+
expect(result.success).toBe(true);
525+
if (result.success) {
526+
expect(result.command.ignoreHTTPSErrors).toBe(false);
527+
}
528+
});
529+
530+
it('should reject launch with non-boolean ignoreHTTPSErrors', () => {
531+
const result = parseCommand(cmd({ id: '1', action: 'launch', ignoreHTTPSErrors: 'true' }));
532+
expect(result.success).toBe(false);
533+
});
513534
});
514535

515536
describe('mouse actions', () => {

0 commit comments

Comments
 (0)