Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support building auditable executables #192

Open
repi opened this issue Sep 9, 2022 · 9 comments
Open

Support building auditable executables #192

repi opened this issue Sep 9, 2022 · 9 comments

Comments

@repi
Copy link

repi commented Sep 9, 2022

The new cargo-auditable, that the Rust Secure WG & @Shnatsel built, is a tool that builds executables with Cargo and embeds a manifest of all of their exact dependencies and versions that can be easily extracted and analysed after the fact to check for security advisories and bugs (for example from RustSec advisory list). A Software Bill of Materials.

While the tool and format is early, I believe it would fit very well into cargo install-update as something to run automatically to embed this information, one builds with cargo auditable build xx instead of cargo build xx, though for integration purposes it could be cleaner to have a library version of cargo-auditable that one could use here instead of depending on another binary.

This would be complementary to #190, as that would verify at upgrade/build-time that an upgraded executable doesn't have any advisories on it (which is great), while the support described in this issue would allow other tools to check after the install that there aren't any new advisories that an installed executable is vulnerable for - or do other types of analysis on the dependency information.

@nabijaczleweli
Copy link
Owner

nabijaczleweli commented Sep 9, 2022

I failed to find an actionable manual in the linked repository, but if this means what I think it means, this is possible on trunk with -r auditable-wrapper, where said wrapper is #!/bin/sh, exec cargo auditable "$@".

If this were less strictly-denominational (as it stands it doesn't look like you can call it directly, and I don't obviously see why not) you could say -r cargo-auditable.

The ergonomics of speccing -r every time are questionable, but this could be resolved with the dreaded global config file, if this is a reasonable solution.

@Shnatsel
Copy link

Shnatsel commented Sep 9, 2022

FWIW the format probably isn't going to change in backwards-incompatible ways. I've experimented with it a fair bit and I think this is its final form. We may still add fields, but the core of it should be stable. I really should update the README with that information.

Regarding the library version, I don't think that's feasible because the cargo-auditable binary still needs to exist, since it acts as a rustc wrapper - i.e. it is invoked in place of rustc by Cargo, appends some flags, and invokes the actual rustc.

Right now you can achieve the same effect as running cargo auditable build xx by setting the RUSTC_WORKSPACE_WRAPPER environment variable to the path to cargo-auditable binary, but off the top of my head I'm not sure if I can guarantee that this will always be sufficient.

If this were less strictly-denominational (as it stands it doesn't look like you can call it directly, and I don't obviously see why not) you could say -r cargo-auditable.

I was not aware of use cases that would require direct invocation without any parameters, and wanted to play it safe with the rustc wrapper binary - if it's passed incorrect arguments, it would just error out instead of setting an environment variable and terminating without actually injecting any audit data.

@Shnatsel
Copy link

Shnatsel commented Sep 9, 2022

failed to find an actionable manual in the linked repository

What questions did you have that were not answered by the existing documentation? I'd be happy to improve docs based on feedback!

@nabijaczleweli
Copy link
Owner

-r sets what cargo to run for installationscargo install-update -r zygfryd crate would run zygfryd install --version 1.2.3 --registry crates-io crate.

If cargo-auditable whatever... were equivalent to cargo auditable whatever... then this is, essentially, just a matter of hooking a config file into cargo-update to change the -r default of "cargo" to the configured "cargo-auditable".

Well, as for questions, I didn't have any because I read the code, but I didn't see anything resembling a normal manual, or indeed so much as a usage string, so the fact that cargo-auditable even checks its arguments beyond if(argv[1] == "auditable"sv) ++optind; and explodes if argv[1] isn't "auditable" or "rustc" was surprising.

@Shnatsel
Copy link

Shnatsel commented Sep 9, 2022

Could you point me to what "a normal manual" looks like? I don't think you mean a unix manpage.

There is no usage string (-h output) listed because there are no custom arguments that the command accepts. It just forwards everything to cargo.

The exploding when called directly instead of via cargo auditable is typical for Cargo subcommands. I have allowed direct invocations in some of mine, but I don't think being lenient and accepting direct calls as opposed to cargo auditable or on the lower level cargo-auditable auditable would work. cargo rustc is a valid invocation, but the rustc parameter is the only reliable way to tell that the binary is being called as a rustc wrapper, so there would be a collision there. This could potentially be solved by splitting cargo auditable into two binaries, the Cargo subcommand and the rustc wrapper, but that means it can no longer be used when it's not in $PATH, so that's a trade-off.

Perhaps the -r flag could be extended to support not just the binary, but arguments as well, so that -r 'cargo auditable' would just work?

@nabijaczleweli
Copy link
Owner

nabijaczleweli commented Sep 9, 2022

I do mean a UNIX manual, something like

.Dd
.Dt CARGO-AUDITABLE 1
.Os
.
.Sh NAME
.Nm cargo-auditable
.Nd inject dependency tree into built executables
.
.Sh SYNOPSIS
.Nm cargo Cm auditable Ar argument Ns 
.Nm cargo Cm rustc Ar argument Ns 
.
.Nm Cm auditable Ar argument Ns 
.Nm Cm rustc Ar argument Ns 
.
.Sh DESCRIPTION
If the first argument is
.Cm auditable ,
executes
.Nm cargo Ar argument Ns s
with
.Ev RUSTC_WORKSPACE_WRAPPER
set to &c., which affects, &c.

you get the picture.

Nah, I'm already surprised we field-split $CARGO_INSTALL_OPTS (on spaces only(!?), it's fine for what it's for, I guess, i.e. #119), but field-splitting paths is a 1986ism I try to avoid (and get functional Win32 support for free as a result).

In this case, and if cargo auditable install works (which I'm assuming it does but the README doesn't say anything that matches "install" and only uses build as the cargo verb, so idk), then passing an executable with the following to -r should Just Work:

#!/bin/sh
exec cargo auditable "$@"

@Shnatsel
Copy link

Shnatsel commented Sep 9, 2022

In this case, and if cargo auditable install works (which I'm assuming it does but the README doesn't say anything that matches "install" and only uses build as the cargo verb, so idk)

Ah! Good point. Yes, that works. I'll go ahead and explain it in the README. Thanks for the feedback!

@Shnatsel
Copy link

Shnatsel commented Sep 9, 2022

field-splitting paths is a 1986ism I try to avoid (and get functional Win32 support for free as a result).

How about passing that to the native system shell? I assume that would still work on win32.

@nabijaczleweli
Copy link
Owner

nabijaczleweli commented Sep 10, 2022

No clue how that'd affect anything (besides making it more annoying to properly escape the arguments)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants