Security Alert: Tar Permissions

Posted 10 December 2022 by Natalie Weizenbaum

The Sass team was recently alerted by prolific external contributor @ntkme to a security issue in our release process.

TL;DRTL;DR permalink

If you’re using Linux or Mac OS, run ls -ax path/to/sass. If the last group of letters in the first column contains w, you’re vulnerable:

Vulnerable:
-rwxr-xrwx 1 nweiz primarygroup 407 Dec 13 12:33 sass-1.56.2/sass

Not vulnerable:
-rwxr-xr-x 1 nweiz primarygroup 407 Dec 13 12:33 sass-1.56.2/sass

If you’re using the sass-embedded package, do the same thing for node_modules/sass-embedded/dist/lib/src/vendor/dart-sass-embedded/dart-sass-embedded.

Who’s Affected?Who’s Affected? permalink

While we don’t expect this issue to be a problem for the vast majority of users, it does affect the following groups:

  • Users who downloaded the stand-alone Dart Sass, Dart Sass Embedded, or Sass Migrator .tar.gz archives from the Dart Sass website and extracted them as the Unix root user.

  • Users who installed the sass-embedded npm package as the Unix root user prior to version 1.54.5.

  • Users who installed the "non-native" version of the community-maintained sass-embedded RubyGems package as the Unix root user prior to version 1.56.2.

  • Users on multi-user systems who downloaded the stand-alone Dart Sass, Dart Sass Embedded, or Sass Migrator .tar.gz archives from the Dart Sass website and explicitly passed the -p/--preserve-permissions flag when extracting them.

Users who installed Dart Sass via the sass npm package, Homebrew, or Chocolatey are categorically not at risk, nor are users on Windows.

We strongly recommend that users in these vulnerable groups delete and re-install Sass. All the .tar.gz files on GitHub have been scrubbed to remove the vulnerability, so you can reinstall the same version you were previously using without needing to upgrade to the latest version.

This is a privilege-escalation issue, which means it could allow a hypothetical attacker with access to a low-privilege account on your computer to escalate their access to your account’s privileges. However, this also means that it’s not a risk unless an attacker already has access to an account on your machine.

What went wrong?What went wrong? permalink

We were inadvertently uploading .tar.gz archives with permissions metadata indicating that executable files could be overwritten by all users, not just the owner.

In most cases, this metadata is ignored when extracting the archives and the permissions are set to only be writable by the user doing the extraction. However, when extracting archives as the Unix root user or explicitly passing the -p/--preserve-permissions flag, the permissions for the extracted files are set according to the archive’s metadata. Because the metadata was incorrect, an attacker with access to a low-privilege account would be able to overwrite the executable file and escalate their privileges once it’s executed.

How did this happen?How did this happen? permalink

Dart Sass is automatically deployed to various different release platforms using a Dart package called cli_pkg, which is also written maintained by the Sass team. This package uses the Dart archive package to generate .tar.gz files for stand-alone release packages which are then uploaded to GitHub, and when initially writing the code to use this package I wrote the following function:

ArchiveFile fileFromBytes(String path, List<int> data,
        {bool executable = false}) =>
    ArchiveFile(path, data.length, data)
      ..mode = executable ? 495 : 428
      ..lastModTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;

My intention was to set the executable mode to 755 (read/write/execute for the owner, read/execute only for the other users) and the non-executable mode to 644 (read/write for the owner, read-only for other users). However, Dart doesn’t support literal octal numbers and I must have done the decimal-to-octal conversion wrong. The actual permissions that got set were 757 (read/write/execute for the owner and other users, read/execute for the group) and 654 (read/write for the owner, read/execute for the group, and read-only for other users).

This went unnoticed for several years, until @ntkme notified us of the issue last week and provided a fix to cli_pkg.

What’s been done?What’s been done? permalink

We’ve released cli_pkg 2.1.7 which sets the archive permissions correctly. In addition, we’ve updated all .tar.gz files in the Dart Sass, Dart Sass Embedded, and Sass Migrator repositories to correctly limit write permissions to only the owner of the files. We’re announcing the vulnerability here and on the @SassCSS Twitter account.