Security note

This commit is contained in:
SheetJS 2025-04-20 22:17:01 -04:00
parent d953a625a2
commit c0a67806b7
13 changed files with 436 additions and 33 deletions

@ -34,7 +34,7 @@
</Style>
</Styles>
<Worksheet ss:Name="Frameworks">
<Table ss:ExpandedColumnCount="7" ss:ExpandedRowCount="10" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
<Table ss:ExpandedColumnCount="7" ss:ExpandedRowCount="11" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
<Column ss:Index="2" ss:Width="24"/>
<Column ss:Width="31"/>
<Column ss:Width="24"/>
@ -110,6 +110,15 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/cli/txiki"><Data ss:Type="String">txiki.js</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#snapshots"><Data ss:Type="String">V8 Engine</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>

@ -132,8 +132,8 @@
<Cell><Data ss:Type="String">C</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
@ -304,8 +304,8 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#zig"><Data ss:Type="String">Duktape</Data></Cell>

@ -311,6 +311,13 @@ adb exec-out run-as org.sheetjs.quasar cat files/files/SheetJSQuasar.xlsx > /tmp
npx xlsx-cli /tmp/SheetJSQuasar.xlsx
```
:::caution pass
PowerShell file redirects will corrupt binary data. In Windows, commands must be
run from a Command Prompt session.
:::
### iOS
8) Create the iOS project:

@ -54,22 +54,22 @@ For example, the following script accepts one command line argument, parses the
specified file using the SheetJS `readFile` method[^1], generates CSV text from
the first worksheet using `sheet_to_csv`[^2], and prints to terminal:
<CodeBlock language="ts" title="sheet2csv.ts">{`\
```ts title="sheet2csv.ts"
const XLSX = require("xlsx");
\n\
/* process.argv[2] is the first argument to the script */
const filename = process.argv[2];
\n\
/* read file */
const wb = XLSX.readFile(filename);
\n\
/* generate CSV of first sheet */
const ws = wb.Sheets[wb.SheetNames[0]];
const csv = XLSX.utils.sheet_to_csv(ws);
\n\
/* print to terminal */
console.log(csv);`}
</CodeBlock>
console.log(csv);
```
## Complete Example

@ -0,0 +1,247 @@
---
title: TxikiJS Standalone Apps
sidebar_label: txiki.js
pagination_prev: demos/desktop/index
pagination_next: demos/data/index
sidebar_custom_props:
summary: Compiled apps powered by QuickJS and txiki.js
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
`txiki.js` is a small runtime powered by [QuickJS](/docs/demos/engines/quickjs).
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo uses `txiki.js` and SheetJS to create a standalone CLI tool for
parsing spreadsheets and generating CSV rows.
:::caution TxikiJS support is considered experimental.
Great open source software grows with user tests and reports. Any issues should
be reported to the `txiki.js` project for further diagnosis.
:::
## Integration Details
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
can be evaluated and consumed in TxikiJS.
The platform provides APIs for filesystem operations that differ from NodeJS:
- `tjs.readFile` reads raw data from a specified filename and returns a Promise
that resolves to a `Uint8Array`
- `tjs.args` is an array of arguments. In the compiled program, the first value
will be the program name and the second value will be the first argument.
The SheetJS filesystem methods ([`readFile`](/docs/api/parse-options) and
[`writeFile`](/docs/api/parse-options)) do not recognize the `txiki.js` APIs.
Fortunately, `read` and `write` directly work with `Uint8Array` data.
The following example reads and parses `pres.xlsx` in the current directory:
```js title="Parse pres.xlsx in TxikiJS"
/* read data from pres.xlsx into a Uint8Array */
const data = await tjs.readFile("pres.xlsx");
/* parse data and generate a SheetJS workbook object */
const wb = XLSX.read(data);
```
### Script Requirements
The compiler does not bundle scripts automatically. Scripts that exclusively use
web APIs, SheetJS API methods, and `tjs` API methods can be bundled and compiled.
[`esbuild`](/docs/demos/frontend/bundler/esbuild) is the recommended bundler.
For example, the following script accepts one command line argument, parses the
specified file using `tjs.readFile` and the SheetJS `read` method[^1], generates
CSV text from the first sheet using `sheet_to_csv`[^2], and prints the result:
```js title="sheet2csv.js (before bundling)"
const XLSX = require("./xlsx.full.min");
/* tjs.args[1] is the first argument to the script */
const filename = tjs.args[1];
/* read and parse file */
const data = await tjs.readFile(filename);
const wb = XLSX.read(data);
/* generate CSV of first sheet */
const ws = wb.Sheets[wb.SheetNames[0]];
const csv = XLSX.utils.sheet_to_csv(ws);
/* print to terminal */
console.log(csv);
```
## Complete Example
:::note Tested Deployments
This demo was tested in the following deployments:
| Architecture | TxikiJS | Date |
|:-------------|:----------|:-----------|
| `darwin-x64` | `24.12.0` | 2025-04-19 |
| `darwin-arm` | `24.12.0` | 2025-04-19 |
| `win11-x64` | `24.12.0` | 2025-04-19 |
| `win11-arm` | `24.12.0` | 2025-04-19 |
| `linux-x64` | `24.12.0` | 2025-04-19 |
| `linux-arm` | `24.12.0` | 2025-04-19 |
:::
:::caution pass
TxikiJS on Windows on ARM uses the X64 compatibility layer. It does not generate
a native ARM64 binary!
:::
0) Create a new project folder and download `txiki.js`[^3]:
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
```bash
mkdir sheetjs-txiki
cd sheetjs-txiki
curl -LO https://github.com/saghul/txiki.js/releases/download/v24.12.0/txiki-macos.zip
unzip txiki-macos.zip
mv txiki-macos/tjs .
chmod +x tjs
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
```bash
mkdir sheetjs-txiki
cd sheetjs-txiki
git clone --recursive https://github.com/saghul/txiki.js --shallow-submodules
cd txiki.js
make
cp build/tjs ../
cd ..
```
</TabItem>
<TabItem value="win11-x64" label="Windows">
```bash
mkdir sheetjs-txiki
cd sheetjs-txiki
curl.exe -LO https://github.com/saghul/txiki.js/releases/download/v24.12.0/txiki-windows-x86_64.zip
tar xf txiki-windows-x86_64.zip
mv txiki-windows-x86_64\* .
```
</TabItem>
</Tabs>
1) Download the test file https://docs.sheetjs.com/pres.numbers:
```bash
curl -LO https://docs.sheetjs.com/pres.numbers
```
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
```bash
curl.exe -LO https://docs.sheetjs.com/pres.numbers
```
:::
2) Save the [contents of the `sheet2csv.js` code block](#script-requirements)
to `sheet2csv.js` in the project folder.
```bash
curl -LO https://docs.sheetjs.com/txikijs/sheet2csv.js
```
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
```bash
curl.exe -LO https://docs.sheetjs.com/txikijs/sheet2csv.js
```
:::
3) Download the SheetJS Standalone script and move to the project directory:
<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
</ul>
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
</CodeBlock>
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
</CodeBlock>
:::
4) Bundle the script:
```js
npx -y esbuild sheet2csv.js --bundle --outfile=bundle.js --platform=neutral
```
5) Compile and run `sheet2csv`:
```bash
./tjs compile bundle.js sheet2csv
./sheet2csv pres.numbers
```
The program should display the same CSV contents as the script:
```text title="Expected Output"
Name,Index
Bill Clinton,42
GeorgeW Bush,43
Barack Obama,44
Donald Trump,45
Joseph Biden,46
```
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^2]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
[^3]: When this demo was last tested, the [ZIP archive for version `24.12.0`](https://github.com/saghul/txiki.js/releases/tag/v24.12.0) was downloaded and extracted.

@ -1115,6 +1115,8 @@ This demo was tested in the following deployments:
| `darwin-x64` | `2.2.1` | 2025-03-31 |
| `darwin-arm` | `2.2.1` | 2025-03-31 |
| `win11-x64` | `2.2.1` | 2025-04-17 |
| `linux-x64` | `2.2.1` | 2025-04-18 |
| `linux-arm` | `2.2.1` | 2025-04-18 |
:::

@ -252,34 +252,29 @@ At this point, `csvstr` is a C string that can be printed to standard output.
## Complete Example
The "Integration Example" covers a traditional integration in a C application,
while the "CLI Test" demonstrates other concepts using the `quickjs` CLI tool.
### Integration Example
- ["Integration Example"](#integration-example) covers a traditional integration
of the official library in a C application.
- ["Windows Example"](#windows-example) uses the QuickJS-NG fork
- ["CLI Test"](#cli-test) uses the `quickjs` CLI tool.
:::note Tested Deployments
This demo was tested in the following deployments:
| Architecture | Git Commit | Date |
|:-------------|:-----------|:-----------|
| `darwin-x64` | `0d7aaed` | 2025-03-31 |
| `darwin-arm` | `6e2e68f` | 2024-12-17 |
| `win11-x64` | `6e2e68f` | 2024-12-19 |
| `win11-arm` | `6e2e68f` | 2025-02-23 |
| `linux-x64` | `6e2e68f` | 2025-01-09 |
| `linux-arm` | `6e2e68f` | 2025-02-15 |
| Architecture | Library | Git Commit | Date |
|:-------------|:-----------|:-----------|:-----------|
| `darwin-x64` | QuickJS | `0d7aaed` | 2025-03-31 |
| `darwin-arm` | QuickJS | `6e2e68f` | 2024-12-17 |
| `win11-x64` | QuickJS-NG | `865ba1f` | 2025-04-18 |
| `win11-arm` | QuickJS-NG | `865ba1f` | 2025-04-18 |
| `linux-x64` | QuickJS | `6e2e68f` | 2025-01-09 |
| `linux-arm` | QuickJS | `6e2e68f` | 2025-02-15 |
When the demo was tested, `0d7aaed` was the HEAD commit on the `master` branch.
:::
:::caution pass
QuickJS does not officially support Windows. The `win11-x64` and `win11-arm`
tests were run entirely within Windows Subsystem for Linux.
:::
### Integration Example
0) Build `libquickjs.a`:
@ -350,6 +345,80 @@ curl -LO https://docs.sheetjs.com/pres.numbers`}
If successful, the program will print the library version number, file size,
first worksheet name, and the contents of the first sheet as CSV rows.
### Windows Example
The [QuickJS-NG fork](https://quickjs-ng.github.io/quickjs/) explicitly aims to
support Windows. It provides a source amalgamation for easy integration.
:::info pass
The Windows build requires Visual Studio with "Desktop development with C++".
Commands must be run in a "Native Tools Command Prompt" session.
:::
0) Create a project folder:
```bash
mkdir sheetjs-quick
cd sheetjs-quick
```
1) Build the QuickJS-NG amalgamation:
```bash
git clone https://github.com/quickjs-ng/quickjs
cd quickjs
git checkout 865ba1f1
cmake -B build -DQJS_BUILD_EXAMPLES=ON
cmake --build build --config Release
build\Release\qjs.exe amalgam.js
cd ..
```
2) Copy `quickjs-amalgam.c` and `quickjs.h` into the working directory:
```
copy quickjs\quickjs-amalgam.c .
copy quickjs\quickjs.h .
```
3) Download [`sheetjs.quick.c`](pathname:///quickjs/sheetjs.quick.c):
```bash
curl -LO https://docs.sheetjs.com/quickjs/sheetjs.quick.c
```
4) Build the sample application:
```bash
cl sheetjs.quick.c quickjs-amalgam.c /std:c11 /experimental:c11atomics /w /I .\
```
This program tries to parse the file specified by the first argument
5) Download the SheetJS Standalone script and test file. Save both files in
the project directory:
<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
<li><a href="https://docs.sheetjs.com/pres.numbers">pres.numbers</a></li>
</ul>
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
6) Run the test program:
```bash
.\sheetjs.quick.exe pres.numbers
```
If successful, the program will print the library version number, file size,
first worksheet name, and the contents of the first sheet as CSV rows.
### CLI Test

@ -0,0 +1,41 @@
---
title: Security
sidebar_position: 7
hide_table_of_contents: true
---
Please report any potential vulnerability or question to security@sheetjs.com
## Known Issues
SheetJS libraries use techniques that may be flagged by overzealous scanners.
**The issues in this section are fundamentally unavoidable.**
### URL References and XML
XLSX, SpreadsheetML2003, and a number of other spreadsheet file formats use XML.
XML namespaces are specified as URLs. For example, XLSX file properties follow
[Dublin Core](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/)
Metadata standards. XLSX files must reference `http://purl.org/dc/elements/1.1/`.
**This is a design flaw of XML!**
Any tool that generates XML files must generate URLs to domains outside of the
control of the vendor.
### Non-ASCII Characters
XLS, CSV and other legacy file formats use system-specific encodings. Excel and
other established software predate UTF-8. As a result, SheetJS libraries ship
with [the `codepage` encodings](/docs/constellation/codepage).
SheetJS libraries include CJK ("Chinese, Japanese and Korean") characters to
support CSV and XLS files generated by East Asian versions of Excel.
**The encodings are required for correct parsing of spreadsheet data!**
[The SheetJS library scripts are reproducible](/docs/miscellany/contributing).
Security-conscious developers should audit the source code and verify that the
build artifacts are identical to the official releases.

@ -1,7 +1,7 @@
---
title: Rational Approximation
pagination_prev: constellation/ssf
pagination_next: constellation/crc32
pagination_next: constellation/codepage
---
<head>

@ -0,0 +1,12 @@
---
title: Legacy Codepages
hide_table_of_contents: true
pagination_prev: constellation/frac/index
---
The SheetJS `codepage` library provides lookup tables and utility functions for
processing data encoded with legacy codepages. It is a core component of file
processing for XLS, CSV, and a number of legacy file formats.
Source code and project documentation are hosted on the SheetJS Git server at
https://git.sheetjs.com/sheetjs/js-codepage

@ -1,7 +1,6 @@
---
title: CRC32 Checksum
hide_table_of_contents: true
pagination_prev: constellation/frac/index
---
<head>

@ -5,7 +5,9 @@ pagination_prev: miscellany/index
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
Many related projects have been separated into dedicated libraries.
For historical and legal reasons, many related projects have been separated into
dedicated libraries and tools. Some projects live in separate repositories and
others live in the [main repo](https://git.sheetjs.com/sheetjs/sheetjs/issues).
### Contents

@ -0,0 +1,15 @@
const XLSX = require("./xlsx.full.min");
/* tjs.args[1] is the first argument to the script */
const filename = tjs.args[1];
/* read and parse file */
const data = await tjs.readFile(filename);
const wb = XLSX.read(data);
/* generate CSV of first sheet */
const ws = wb.Sheets[wb.SheetNames[0]];
const csv = XLSX.utils.sheet_to_csv(ws);
/* print to terminal */
console.log(csv);